Commit 17242131 authored by hjistc's avatar hjistc

UI, 3.0.17

parent 668c1f58
...@@ -4,15 +4,12 @@ ...@@ -4,15 +4,12 @@
position: relative; position: relative;
} }
:host:before { #background {
content: '';
background-image: url('http://vignette2.wikia.nocookie.net/touhou/images/2/2c/Th10_cover.jpg/revision/latest?cb=20071101234746');
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
z-index: -1;
filter: grayscale(50%) opacity(10%); filter: grayscale(50%) opacity(10%);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% auto; background-size: 100% auto;
...@@ -20,7 +17,7 @@ ...@@ -20,7 +17,7 @@
} }
.scroll { .scroll {
padding: 1rem; padding: 1rem 1rem 0 1rem;
height: 100%; height: 100%;
} }
...@@ -59,7 +56,7 @@ progress { ...@@ -59,7 +56,7 @@ progress {
#network { #network {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
width: 300px; width: 230px;
} }
#network .input-group-btn > .btn:not(:last-child):not(.dropdown-toggle) { #network .input-group-btn > .btn:not(:last-child):not(.dropdown-toggle) {
...@@ -87,7 +84,6 @@ progress { ...@@ -87,7 +84,6 @@ progress {
h1 { h1 {
font-size: 28px; font-size: 28px;
margin-left: 1rem;
} }
#status { #status {
...@@ -112,9 +108,10 @@ h2 { ...@@ -112,9 +108,10 @@ h2 {
.panel { .panel {
border: 1px solid #eceeef; border: 1px solid #eceeef;
border-radius: 6px; border-radius: 6px;
background: rgba(255, 255, 255, .7); background: rgba(255,255,255,.7);
padding: .8rem; padding: .8rem;
margin-bottom: 1rem; margin-bottom: 1rem;
box-shadow: 0 0 15px rgba(0,0,0,.05);
position: relative; position: relative;
} }
...@@ -150,4 +147,76 @@ h2 { ...@@ -150,4 +147,76 @@ h2 {
#local h2 { #local h2 {
margin-bottom: .8rem; margin-bottom: .8rem;
} }
\ No newline at end of file
#icon {
width: 128px;
height: 128px;
box-shadow: 0 0 4px #ccc;
}
#main {
display: flex;
flex-direction: row;
}
#right {
margin-left: 1rem;
}
h1 {
font-size: 28px;
margin-bottom: 0;
}
#time {
font-size: 14px;
margin-bottom: .6rem;
}
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-bottom: 0;
}
table th, table td {
border-top: none;
font-size: 14px;
font-weight: normal;
}
/* */
\ No newline at end of file
<div *ngIf="currentApp.background" id="background" [style.background-image]="'url(' + currentApp.background + ')'"></div>
<div class="scroll"> <div class="scroll">
<div id="main" class="panel">
<img *ngIf="currentApp.cover" id="icon" class="rounded" [src]="currentApp.cover">
<div id="right">
<h1>{{currentApp.name}}</h1>
<div id="time">您已玩了 2564 小时</div>
<!--应用未安装-->
<div *ngIf="!currentApp.isInstalled()">
<button i18n (click)="updateInstallOption(currentApp)" type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#install-modal">安装</button>
<button i18n *ngIf="currentApp.runnable()" (click)="updateInstallOption(currentApp)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#import-modal">导入</button>
</div>
<ygopro *ngIf="currentApp.isReady() && (currentApp.id == 'ygopro')" [app]="currentApp" [currentApp]="currentApp"></ygopro> <!--应用变更中-->
<div *ngIf="currentApp.isInstalled() && !currentApp.isReady()">
<div id="status">
<span i18n *ngIf="currentApp.isDownloading()">正在下载</span>
<span i18n *ngIf="currentApp.isInstalling()">正在安装...</span>
<span i18n *ngIf="currentApp.isUninstalling()">正在卸载...</span>
<span i18n *ngIf="currentApp.isWaiting()">等待安装...</span>
<span i18n *ngIf="currentApp.isUpdating()">正在更新...</span>
<span *ngIf="currentApp.status.total">{{(currentApp.status.progress/currentApp.status.total * 100).toFixed()}}%</span>
<span>{{currentApp.progressMessage()}}</span>
</div>
<progress class="progress" [class.progress-striped]="!currentApp.status.total" [class.progress-animated]="!currentApp.status.total" value="{{currentApp.status.total ? currentApp.status.progress : 1}}" max="{{currentApp.status.total}}"></progress>
</div>
<div class="panel panel-default"> <!--应用ready-->
<h2 i18n *ngIf="news && news.length">新闻</h2> <div *ngIf="currentApp.isReady() && (currentApp.id != 'ygopro')">
<div id="news" *ngFor="let item of news"> <button *ngIf="currentApp.runnable()" (click)="runApp(currentApp)" [disabled]="!appsService.allReady(currentApp)" type="button" class="btn btn-primary btn-sm"><i class="fa fa-play" aria-hidden="true"></i> <span i18n>运行</span></button>
<h3>{{item.title}}</h3> <button i18n *ngIf="currentApp.runnable() && currentApp.actions.get('custom')" [disabled]="!appsService.allReady(currentApp)" (click)="custom(currentApp)" type="button" class="btn btn-secondary btn-sm">设置</button>
<span>2017-01-18</span> <div id="network" *ngIf="currentApp.network && currentApp.network.protocol == 'maotama'">
<p>{{item.text}}</p> <div class="input-group input-group-sm">
<a i18n *ngIf="item.url" [href]="item.url" target="_blank">了解更多</a> <input *ngIf="appsService.connections.get(currentApp)" [value]="appsService.connections.get(currentApp).address || 'Loading...'" readonly type="text" class="form-control" title="address">
<div class="input-group-btn" style="flex-direction: row">
<button i18n *ngIf="!appsService.connections.get(currentApp)" [disabled]="!appsService.allReady(currentApp)" (click)="appsService.network(currentApp, currentApp.network.servers[0])" type="button" class="btn btn-secondary btn-sm">联机</button>
<button i18n *ngIf="appsService.connections.get(currentApp)" (click)="copy(appsService.connections.get(currentApp).address)" [disabled]="!appsService.connections.get(currentApp).address" type="button" class="btn btn-secondary btn-sm">复制</button>
<button type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu" [class.dropdown-menu-right]="appsService.connections.get(currentApp)">
<h6 i18n class="dropdown-header">选择服务器</h6>
<a *ngFor="let server of currentApp.network.servers" (click)="appsService.network(currentApp, server)" class="dropdown-item" href="#">{{server.id}}</a>
<div *ngIf="appsService.connections.get(currentApp)" class="dropdown-divider"></div>
<a i18n *ngIf="appsService.connections.get(currentApp)" (click)="appsService.connections.get(currentApp).connection.close()" class="dropdown-item" href="#">取消</a>
</div>
</div>
</div>
</div>
</div>
<ygopro *ngIf="currentApp.isReady() && (currentApp.id == 'ygopro')" [app]="currentApp" [currentApp]="currentApp" (points)="onPoints($event)"></ygopro>
</div> </div>
<a href="https://mycard.moe/ygopro/arena/" target="_blank" class="moreinfo">查看所有新闻</a>
</div> </div>
<div *ngIf="currentApp.isReady()">
<div *ngIf="mods && mods.length"> <!--{"exp":1839,"exp_rank":"9","pt":2207.2901,"arena_rank":"30","win":"703","lose":"568","draw":5,"all":"1276","ratio":"55.09"}-->
<table class="table table-striped">
<thead class="thead-inverse"> <div id="arena" class="panel panel-default" *ngIf="points">
<h2 i18n>排位成绩</h2>
<table class="table table-sm">
<tbody>
<tr> <tr>
<th>#</th> <th>竞技排名</th>
<th i18n>名称</th> <td>{{points.arena_rank}}</td>
<th i18n>操作</th> <th>娱乐排名</th>
<td>{{points.exp_rank}}</td>
</tr> </tr>
</thead> <tr>
<tbody> <th>竞技胜率</th>
<tr *ngFor="let mod of mods; let i = index"> <td>{{points.athletic_wl_ratio}}%</td>
<th scope="row">{{i + 1}}</th> <th>经验</th>
<td>{{mod.name}}</td> <td>{{points.exp}}</td>
<td *ngIf="mod.isReady()"> </tr>
<button i18n type="button" [disabled]="mod.isInstalled()&&!appsService.allReady(mod)" (click)="uninstall(mod)" class="btn btn-danger btn-sm">卸载</button> <tr>
</td> <th>胜场</th>
<td *ngIf="!mod.isInstalled()"> <td>{{points.athletic_win}}</td>
<button i18n (click)="installMod(mod)" [disabled]="mod.isInstalled()&&!appsService.allReady(mod)" type="button" *ngIf="!mod.isInstalled()" class="btn btn-primary btn-sm">安装</button> <th>胜场</th>
</td> <td>{{points.entertain_win}}</td>
<td *ngIf="mod.isInstalled()&&!mod.isReady()"> </tr>
<progress class="progress progress-striped progress-animated" value="{{mod.status.total ? mod.status.progress : 1}}" max="{{mod.status.total}}"></progress> <tr>
<!--<div i18n *ngIf="mod.isWaiting()">等待安装...</div>--> <th>负场</th>
</td> <td>{{points.entertain_lose}}</td>
<th>负场</th>
<td>{{points.entertain_lose}}</td>
</tr>
<tr>
<th>平局</th>
<td>{{points.athletic_draw}}</td>
<th>平局</th>
<td>{{points.entertain_draw}}</td>
</tr>
<tr>
<th>总场</th>
<td>{{points.athletic_all}}</td>
<th>总场</th>
<td>{{points.entertain_all}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<a i18n href="https://mycard.moe/ygopro/arena/" target="_blank" class="moreinfo">更多资料</a>
</div>
<!--<div *ngIf="points" class="row">-->
<!--<dl class="col-4 row">-->
<!--<dt i18n class="col-8">竞技排名</dt>-->
<!--<dd class="col-4">{{points.arena_rank}}</dd>-->
<!--<dt i18n class="col-8">竞技胜率</dt>-->
<!--<dd class="col-4">{{points.athletic_wl_ratio}}%</dd>-->
<!--<dt i18n class="col-8">胜场</dt>-->
<!--<dd class="col-4">{{points.athletic_win}}</dd>-->
<!--<dt i18n class="col-8">负场</dt>-->
<!--<dd class="col-4">{{points.athletic_lose}}</dd>-->
<!--<dt i18n class="col-8">平局</dt>-->
<!--<dd class="col-4">{{points.athletic_draw}}</dd>-->
<!--<dt i18n class="col-8">总场</dt>-->
<!--<dd class="col-4">{{points.athletic_all}}</dd>-->
<!--</dl>-->
<!--<dl class="col-4 row">-->
<!--<dt i18n class="col-8">娱乐排名</dt>-->
<!--<dd class="col-4">{{points.exp_rank}}</dd>-->
<!--<dt i18n class="col-8">经验</dt>-->
<!--<dd class="col-4">{{points.exp}}</dd>-->
<!--<dt i18n class="col-8">胜场</dt>-->
<!--<dd class="col-4">{{points.entertain_win}}</dd>-->
<!--<dt i18n class="col-8">负场</dt>-->
<!--<dd class="col-4">{{points.entertain_lose}}</dd>-->
<!--<dt i18n class="col-8">平局</dt>-->
<!--<dd class="col-4">{{points.entertain_draw}}</dd>-->
<!--<dt i18n class="col-8">总场</dt>-->
<!--<dd class="col-4">{{points.entertain_all}}</dd>-->
<!--</dl>-->
<!--</div>-->
<div class="panel panel-default" *ngIf="news && news.length">
<h2 i18n>新闻</h2>
<div id="news" *ngFor="let item of news">
<h3>{{item.title}}</h3>
<span>2017-01-18</span>
<p>{{item.text}}</p>
<a i18n *ngIf="item.url" [href]="item.url" target="_blank">了解更多</a>
</div>
<!--<a href="https://mycard.moe/ygopro/arena/" target="_blank" class="moreinfo">查看所有新闻</a>-->
</div> </div>
<div *ngIf="currentApp.isReady()">
<div *ngIf="mods && mods.length">
<table class="table table-striped">
<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 *ngIf="mod.isReady()">
<button i18n type="button" [disabled]="mod.isInstalled()&&!appsService.allReady(mod)" (click)="uninstall(mod)" class="btn btn-danger btn-sm">卸载</button>
</td>
<td *ngIf="!mod.isInstalled()">
<button i18n (click)="installMod(mod)" [disabled]="mod.isInstalled()&&!appsService.allReady(mod)" type="button" *ngIf="!mod.isInstalled()" class="btn btn-primary btn-sm">安装</button>
</td>
<td *ngIf="mod.isInstalled()&&!mod.isReady()">
<progress class="progress progress-striped 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>
</div>
<div class="panel panel-default" id="local"> <div class="panel panel-default" id="local">
<h2 i18n>本地文件</h2> <h2 i18n>本地文件</h2>
<div> <div>
...@@ -54,101 +184,100 @@ ...@@ -54,101 +184,100 @@
</div> </div>
</div>
</div> <!--安装modal-->
<div class="modal fade" id="install-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" *ngIf="installOption">
<!--安装modal--> <div class="modal-dialog" role="document">
<div class="modal fade" id="install-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" *ngIf="installOption"> <form id="install-form" class="modal-content" (ngSubmit)="install(currentApp,installOption,referencesInstall)" #theForm="ngForm">
<div class="modal-dialog" role="document"> <div class="modal-header">
<form id="install-form" class="modal-content" (ngSubmit)="install(currentApp,installOption,referencesInstall)" #theForm="ngForm"> <h5 i18n class="modal-title" id="myModalLabel">安装 {{currentApp.name}}</h5>
<div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<h5 i18n class="modal-title" id="myModalLabel">安装 {{currentApp.name}}</h5> <span>&times;</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> </button>
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<p i18n>即将开始安装 {{currentApp.name}}</p>
<h4 i18n>安装位置</h4>
<div class="form-group">
<select class="form-control" name="installPath" (change)="selectLibrary()" [(ngModel)]="installOption.installLibrary" title="path">
<option *ngFor="let library of libraries" value="{{library}}"> {{library}}</option>
<option *ngFor="let library of availableLibraries" value="create_{{library}}">在 {{library}}\ 盘新建 MyCard 库</option>
</select></div>
<h4 i18n>快捷方式</h4>
<div class="checkbox">
<input id="create_application_shortcut" type="checkbox" name="application" [(ngModel)]="installOption.createShortcut">
<label i18n *ngIf="platform == 'darwin'" for="create_application_shortcut">创建 LaunchPad 快捷方式</label>
<label i18n *ngIf="platform == 'win32'" for="create_application_shortcut">创建开始菜单快捷方式</label>
</div> </div>
<div class="checkbox"> <div class="modal-body">
<input id="create_desktop_shortcut" type="checkbox" name="desktop" [(ngModel)]="installOption.createDesktopShortcut"> <p i18n>即将开始安装 {{currentApp.name}}</p>
<label i18n for="create_desktop_shortcut">创建桌面快捷方式</label> <h4 i18n>安装位置</h4>
<div class="form-group">
<select class="form-control" name="installPath" (change)="selectLibrary()" [(ngModel)]="installOption.installLibrary" title="path">
<option *ngFor="let library of libraries" value="{{library}}"> {{library}}</option>
<option *ngFor="let library of availableLibraries" value="create_{{library}}">在 {{library}}\ 盘新建 MyCard 库</option>
</select></div>
<h4 i18n>快捷方式</h4>
<div class="checkbox">
<input id="create_application_shortcut" type="checkbox" name="application" [(ngModel)]="installOption.createShortcut">
<label i18n *ngIf="platform == 'darwin'" for="create_application_shortcut">创建 LaunchPad 快捷方式</label>
<label i18n *ngIf="platform == 'win32'" for="create_application_shortcut">创建开始菜单快捷方式</label>
</div>
<div class="checkbox">
<input id="create_desktop_shortcut" type="checkbox" name="desktop" [(ngModel)]="installOption.createDesktopShortcut">
<label i18n for="create_desktop_shortcut">创建桌面快捷方式</label>
</div>
<h4 i18n *ngIf="references.length>0">扩展内容</h4>
<div *ngFor="let reference of references"><label>
<input type="checkbox" [(ngModel)]="referencesInstall[reference.id]" name="references"> {{reference.name}}
</label></div>
<div *ngIf="currentApp.findDependencies().length">
<span i18n>依赖:</span>
<span class="dependency" *ngFor="let dependency of currentApp.findDependencies()">{{dependency.name}}</span>
</div>
</div> </div>
<h4 i18n *ngIf="references.length>0">扩展内容</h4> <div class="modal-footer">
<div *ngFor="let reference of references"><label> <button i18n type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<input type="checkbox" [(ngModel)]="referencesInstall[reference.id]" name="references"> {{reference.name}} <button i18n type="submit" [disabled]="!theForm.form.valid" class="btn btn-primary">安装</button>
</label></div>
<div *ngIf="currentApp.findDependencies().length">
<span i18n>依赖:</span>
<span class="dependency" *ngFor="let dependency of currentApp.findDependencies()">{{dependency.name}}</span>
</div> </div>
</div> </form>
<div class="modal-footer"> </div>
<button i18n type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button i18n type="submit" [disabled]="!theForm.form.valid" class="btn btn-primary">安装</button>
</div>
</form>
</div> </div>
</div>
<div class="modal fade" id="import-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" *ngIf="installOption">
<div class="modal fade" id="import-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" *ngIf="installOption"> <div class="modal-dialog" role="document">
<div class="modal-dialog" role="document"> <form id="import-form" class="modal-content" (ngSubmit)="importGame(currentApp,installOption,referencesInstall)" #theForm="ngForm">
<form id="import-form" class="modal-content" (ngSubmit)="importGame(currentApp,installOption,referencesInstall)" #theForm="ngForm"> <div class="modal-header">
<div class="modal-header"> <h5 i18n class="modal-title">导入 {{currentApp.name}}</h5>
<h5 i18n class="modal-title">导入 {{currentApp.name}}</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span>&times;</span>
<span>&times;</span> </button>
</button>
</div>
<div class="modal-body">
<p i18n>选择主程序 {{currentApp.actions.get('main').execute}}</p>
<label class="custom-file" lang="en">
<input (click)="$event.preventDefault();selectImport(currentApp)" type="file" id="file" class="custom-file-input">
<span class="custom-file-control">{{import_path || currentApp.actions.get('main').execute}}</span>
</label>
<h4 i18n>导入到</h4>
<div class="form-group">
<select class="form-control" name="installPath" (change)="selectLibrary()" [(ngModel)]="installOption.installLibrary" title="path">
<option *ngFor="let library of libraries" value="{{library}}"> {{library}}</option>
<option *ngFor="let library of availableLibraries" value="create_{{library}}">在 {{library}}\ 盘新建 MyCard 库</option>
</select>
</div> </div>
<!--<h4 i18n>快捷方式</h4>--> <div class="modal-body">
<!--<div class="checkbox">--> <p i18n>选择主程序 {{currentApp.actions.get('main').execute}}</p>
<!--<input id="create_application_shortcut" type="checkbox" name="application" [(ngModel)]="installOption.createShortcut">--> <label class="custom-file" lang="en">
<!--<label i18n *ngIf="platform == 'darwin'" for="create_application_shortcut">创建 LaunchPad 快捷方式</label>--> <input (click)="$event.preventDefault();selectImport(currentApp)" type="file" id="file" class="custom-file-input">
<!--<label i18n *ngIf="platform == 'win32'" for="create_application_shortcut">创建开始菜单快捷方式</label>--> <span class="custom-file-control">{{import_path || currentApp.actions.get('main').execute}}</span>
<!--</div>--> </label>
<!--<div class="checkbox">-->
<!--<input id="create_desktop_shortcut" type="checkbox" name="desktop" [(ngModel)]="installOption.createDesktopShortcut">--> <h4 i18n>导入到</h4>
<!--<label i18n for="create_desktop_shortcut">创建桌面快捷方式</label>--> <div class="form-group">
<!--</div>--> <select class="form-control" name="installPath" (change)="selectLibrary()" [(ngModel)]="installOption.installLibrary" title="path">
<h4 i18n *ngIf="references.length>0">扩展内容</h4> <option *ngFor="let library of libraries" value="{{library}}"> {{library}}</option>
<div *ngFor="let reference of references"><label> <option *ngFor="let library of availableLibraries" value="create_{{library}}">在 {{library}}\ 盘新建 MyCard 库</option>
<input type="checkbox" [(ngModel)]="referencesInstall[reference.id]" name="references"> {{reference.name}} </select>
</label></div> </div>
<div *ngIf="currentApp.findDependencies().length"> <!--<h4 i18n>快捷方式</h4>-->
<span i18n>依赖:</span> <!--<div class="checkbox">-->
<span class="dependency" *ngFor="let dependency of currentApp.findDependencies()">{{dependency.name}}</span> <!--<input id="create_application_shortcut" type="checkbox" name="application" [(ngModel)]="installOption.createShortcut">-->
<!--<label i18n *ngIf="platform == 'darwin'" for="create_application_shortcut">创建 LaunchPad 快捷方式</label>-->
<!--<label i18n *ngIf="platform == 'win32'" for="create_application_shortcut">创建开始菜单快捷方式</label>-->
<!--</div>-->
<!--<div class="checkbox">-->
<!--<input id="create_desktop_shortcut" type="checkbox" name="desktop" [(ngModel)]="installOption.createDesktopShortcut">-->
<!--<label i18n for="create_desktop_shortcut">创建桌面快捷方式</label>-->
<!--</div>-->
<h4 i18n *ngIf="references.length>0">扩展内容</h4>
<div *ngFor="let reference of references"><label>
<input type="checkbox" [(ngModel)]="referencesInstall[reference.id]" name="references"> {{reference.name}}
</label></div>
<div *ngIf="currentApp.findDependencies().length">
<span i18n>依赖:</span>
<span class="dependency" *ngFor="let dependency of currentApp.findDependencies()">{{dependency.name}}</span>
</div>
</div> </div>
</div> <div class="modal-footer">
<div class="modal-footer"> <button i18n type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button i18n type="button" class="btn btn-secondary" data-dismiss="modal">取消</button> <button i18n type="submit" [disabled]="import_path && !theForm.form.valid" class="btn btn-primary">导入</button>
<button i18n type="submit" [disabled]="import_path && !theForm.form.valid" class="btn btn-primary">导入</button> </div>
</div> </form>
</form> </div>
</div> </div>
</div>
</div> </div>
\ No newline at end of file
import {Component, OnInit, Input, ChangeDetectorRef} from '@angular/core'; import {Component, OnInit, Input, ChangeDetectorRef, OnChanges, SimpleChanges} from '@angular/core';
import {AppsService} from './apps.service'; import {AppsService} from './apps.service';
import {InstallOption} from './install-option'; import {InstallOption} from './install-option';
import {SettingsService} from './settings.sevices'; import {SettingsService} from './settings.sevices';
...@@ -8,6 +8,7 @@ import {clipboard, remote} from 'electron'; ...@@ -8,6 +8,7 @@ import {clipboard, remote} from 'electron';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import * as $ from 'jquery'; import * as $ from 'jquery';
import {Points} from './ygopro.component';
declare const Notification: any; declare const Notification: any;
...@@ -17,7 +18,7 @@ declare const Notification: any; ...@@ -17,7 +18,7 @@ declare const Notification: any;
templateUrl: 'app-detail.component.html', templateUrl: 'app-detail.component.html',
styleUrls: ['app-detail.component.css'], styleUrls: ['app-detail.component.css'],
}) })
export class AppDetailComponent implements OnInit { export class AppDetailComponent implements OnInit, OnChanges {
@Input() @Input()
currentApp: App; currentApp: App;
platform = process.platform; platform = process.platform;
...@@ -28,11 +29,26 @@ export class AppDetailComponent implements OnInit { ...@@ -28,11 +29,26 @@ export class AppDetailComponent implements OnInit {
referencesInstall: {[id: string]: boolean}; referencesInstall: {[id: string]: boolean};
import_path: string; import_path: string;
background: string;
points: Points;
constructor(private appsService: AppsService, private settingsService: SettingsService, constructor(private appsService: AppsService, private settingsService: SettingsService,
private downloadService: DownloadService, private ref: ChangeDetectorRef) { private downloadService: DownloadService, private ref: ChangeDetectorRef) {
} }
ngOnChanges(changes: SimpleChanges): void {
if (changes['currentApp']) {
if (this.currentApp.background && this.currentApp.background.length > 0) {
let url = this.currentApp.background[Math.floor(Math.random() * this.currentApp.background.length)];
this.background = `url(${url})`;
} else {
this.background = '';
}
}
}
async ngOnInit(): Promise<void> { async ngOnInit(): Promise<void> {
let volume = 'A'; let volume = 'A';
for (let i = 0; i < 26; i++) { for (let i = 0; i < 26; i++) {
...@@ -216,4 +232,8 @@ export class AppDetailComponent implements OnInit { ...@@ -216,4 +232,8 @@ export class AppDetailComponent implements OnInit {
} }
} }
onPoints(points: Points) {
this.points = points;
}
} }
...@@ -72,6 +72,10 @@ export class App { ...@@ -72,6 +72,10 @@ export class App {
files: Map<string, FileOptions>; files: Map<string, FileOptions>;
data: any; data: any;
icon: string;
cover: string;
background: string;
static downloadUrl (app: App, platform: string, locale: string): string { static downloadUrl (app: App, platform: string, locale: string): string {
if (app.id === 'ygopro') { if (app.id === 'ygopro') {
return `https://thief.mycard.moe/metalinks/${app.id}-${process.platform}-${locale}/${app.version}`; return `https://thief.mycard.moe/metalinks/${app.id}-${process.platform}-${locale}/${app.version}`;
...@@ -165,6 +169,10 @@ export class App { ...@@ -165,6 +169,10 @@ export class App {
this.conference = app.conference; this.conference = app.conference;
this.files = app.files; this.files = app.files;
this.data = app.data; this.data = app.data;
this.icon = app.icon;
this.cover = app.cover;
this.background = app.background;
} }
findDependencies(): App[] { findDependencies(): App[] {
......
...@@ -35,7 +35,6 @@ import 'node_modules/candy-shop/modify-role/candy.js'; ...@@ -35,7 +35,6 @@ import 'node_modules/candy-shop/modify-role/candy.js';
import 'node_modules/candy-shop/me-does/candy.js'; import 'node_modules/candy-shop/me-does/candy.js';
import 'node_modules/candy-shop/notifications/candy.js'; import 'node_modules/candy-shop/notifications/candy.js';
import 'node_modules/candy-shop/refocus/candy.js'; import 'node_modules/candy-shop/refocus/candy.js';
import 'electron-cookies';
delete window['jQuery']; delete window['jQuery'];
...@@ -59,7 +58,8 @@ Candy.Util.getPosTopAccordingToWindowBounds = new Proxy(Candy.Util.getPosTopAcco ...@@ -59,7 +58,8 @@ Candy.Util.getPosTopAccordingToWindowBounds = new Proxy(Candy.Util.getPosTopAcco
} }
}); });
Candy.Util.setCookie('candy-nostatusmessages', '1', 365); document['__defineGetter__']('cookie', () => 'candy-nostatusmessages');
document['__defineSetter__']('cookie', () => true);
@Component({ @Component({
moduleId: module.id, moduleId: module.id,
...@@ -75,10 +75,10 @@ export class CandyComponent implements OnInit, OnChanges { ...@@ -75,10 +75,10 @@ export class CandyComponent implements OnInit, OnChanges {
password: string; password: string;
nickname: string; nickname: string;
constructor (private loginService: LoginService, private settingsService: SettingsService, private element: ElementRef) { constructor(private loginService: LoginService, private settingsService: SettingsService, private element: ElementRef) {
} }
ngOnInit () { ngOnInit() {
this.jid = this.loginService.user.username + '@mycard.moe'; this.jid = this.loginService.user.username + '@mycard.moe';
this.password = this.loginService.user.external_id.toString(); this.password = this.loginService.user.external_id.toString();
...@@ -136,7 +136,7 @@ export class CandyComponent implements OnInit, OnChanges { ...@@ -136,7 +136,7 @@ export class CandyComponent implements OnInit, OnChanges {
Candy.Core.connect(this.jid, this.password, this.nickname); Candy.Core.connect(this.jid, this.password, this.nickname);
} }
ngOnChanges (changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (!Candy.Core.getConnection()) { if (!Candy.Core.getConnection()) {
return; return;
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
display: flex; display: flex;
height: 100%; height: 100%;
} }
#right { #right {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -166,19 +167,23 @@ nav { ...@@ -166,19 +167,23 @@ nav {
a { a {
cursor: default; cursor: default;
} }
.search { .search {
background-color: #ebf3f8; background-color: #ebf3f8;
border: none; border: none;
} }
i.search { i.search {
color: #a7a7a7; color: #a7a7a7;
} }
input.search { input.search {
padding-left: 0; padding-left: 0;
font-size: 14px; font-size: 14px;
font-family: -apple-system, Arial, 'Source Sans Pro', "Microsoft YaHei", 'Microsoft JhengHei', "WenQuanYi Micro Hei", sans-serif; font-family: -apple-system, Arial, 'Source Sans Pro', "Microsoft YaHei", 'Microsoft JhengHei', "WenQuanYi Micro Hei", sans-serif;
} }
input.search::-webkit-input-placeholder{
input.search::-webkit-input-placeholder {
color: #a7a7a7; color: #a7a7a7;
} }
...@@ -229,4 +234,28 @@ nav::-webkit-resizer { ...@@ -229,4 +234,28 @@ nav::-webkit-resizer {
left: 0; left: 0;
right: 0; right: 0;
cursor: row-resize; cursor: row-resize;
} }
\ No newline at end of file
#nav-wrapper {
z-index: 90;
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
}
#candy-wrapper {
z-index: 80;
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
}
roster {
z-index: 90;
}
/*#right-shadow {*/
/*width: 190px;*/
/*z-index: 95;*/
/*box-shadow: 0 0 5px rgba(0, 0, 0, .2);*/
/*position: absolute;*/
/*top: 0;*/
/*right: 0;*/
/*bottom: 0;*/
/*}*/
\ No newline at end of file
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<ul *ngIf="grouped_apps.installed" class="nav nav-pills flex-column"> <ul *ngIf="grouped_apps.installed" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.installed" class="nav-item"> <li *ngFor="let app of grouped_apps.installed" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" class="nav-link" [class.active]="app===currentApp" [href]="'https://mycard.moe/' + app.id"> <a (click)="$event.preventDefault(); chooseApp(app)" class="nav-link" [class.active]="app===currentApp" [href]="'https://mycard.moe/' + app.id">
<img class="icon" src="https://lh3.googleusercontent.com/-crYEtoQ-4Ho/AAAAAAAAAAI/AAAAAAAAAAA/AKB_U8u0CDmxkVqQgOKesrJIb-6eiXacgA/s32-c-mo/photo.jpg"> <img *ngIf="app.icon" class="icon" [src]="app.icon">
{{app.name}}<i *ngIf="!app.isReady() && !app.status.total" class="spin fa fa-circle-o-notch fa-spin fa-fw"></i> {{app.name}}<i *ngIf="!app.isReady() && !app.status.total" class="spin fa fa-circle-o-notch fa-spin fa-fw"></i>
<div *ngIf="!app.isReady() && app.status.total" class="progress"> <div *ngIf="!app.isReady() && app.status.total" class="progress">
<div class="pie" [class.second-half]="app.status.progress/app.status.total>0.5"> <div class="pie" [class.second-half]="app.status.progress/app.status.total>0.5">
...@@ -26,31 +26,31 @@ ...@@ -26,31 +26,31 @@
<span i18n *ngIf="grouped_apps.recommend">推荐</span> <span i18n *ngIf="grouped_apps.recommend">推荐</span>
<ul *ngIf="grouped_apps.recommend" class="nav nav-pills flex-column"> <ul *ngIf="grouped_apps.recommend" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.recommend" class="nav-item"> <li *ngFor="let app of grouped_apps.recommend" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp">{{app.name}}</a> <a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp"><img *ngIf="app.icon" class="icon" [src]="app.icon">{{app.name}}</a>
</li> </li>
</ul> </ul>
<span i18n *ngIf="grouped_apps.mysterious">迷之物体</span> <span i18n *ngIf="grouped_apps.mysterious">迷之物体</span>
<ul *ngIf="grouped_apps.mysterious" class="nav nav-pills flex-column"> <ul *ngIf="grouped_apps.mysterious" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.mysterious" class="nav-item"> <li *ngFor="let app of grouped_apps.mysterious" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp">{{app.name}}</a> <a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp"><img *ngIf="app.icon" class="icon" [src]="app.icon">{{app.name}}</a>
</li> </li>
</ul> </ul>
<span i18n *ngIf="grouped_apps.touhou">东方 Project</span> <span i18n *ngIf="grouped_apps.touhou">东方 Project</span>
<ul *ngIf="grouped_apps.touhou" class="nav nav-pills flex-column"> <ul *ngIf="grouped_apps.touhou" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.touhou" class="nav-item"> <li *ngFor="let app of grouped_apps.touhou" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp">{{app.name}}</a> <a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp"><img *ngIf="app.icon" class="icon" [src]="app.icon">{{app.name}}</a>
</li> </li>
</ul> </ul>
<span i18n *ngIf="grouped_apps.touhou_pc98">东方旧作</span> <span i18n *ngIf="grouped_apps.touhou_pc98">东方旧作</span>
<ul *ngIf="grouped_apps.touhou_pc98" class="nav nav-pills flex-column"> <ul *ngIf="grouped_apps.touhou_pc98" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.touhou_pc98" class="nav-item"> <li *ngFor="let app of grouped_apps.touhou_pc98" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp">{{app.name}}</a> <a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp"><img *ngIf="app.icon" class="icon" [src]="app.icon">{{app.name}}</a>
</li> </li>
</ul> </ul>
<span i18n *ngIf="grouped_apps.runtime_installed">已安装的运行库</span> <span i18n *ngIf="grouped_apps.runtime_installed">已安装的运行库</span>
<ul *ngIf="grouped_apps.runtime_installed" class="nav nav-pills flex-column"> <ul *ngIf="grouped_apps.runtime_installed" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.runtime_installed" class="nav-item"> <li *ngFor="let app of grouped_apps.runtime_installed" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp">{{app.name}}</a> <a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp"><img *ngIf="app.icon" class="icon" [src]="app.icon">{{app.name}}</a>
</li> </li>
</ul> </ul>
</nav> </nav>
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
<div id="right"> <div id="right">
<div id="main"> <div id="main">
<app-detail *ngIf="currentApp" [currentApp]="currentApp"></app-detail> <app-detail *ngIf="currentApp" [currentApp]="currentApp"></app-detail>
<roster class="scroll"></roster> <roster class="scroll"></roster>
...@@ -70,3 +69,5 @@ ...@@ -70,3 +69,5 @@
<candy *ngIf="currentApp" [currentApp]="currentApp"></candy> <candy *ngIf="currentApp" [currentApp]="currentApp"></candy>
</div> </div>
</div> </div>
<div id="right-shadow"></div>
\ No newline at end of file
:host {
background-color: white;
}
.page { .page {
flex-grow: 1; flex-grow: 1;
/*margin-bottom: 60px;*/ /*margin-bottom: 60px;*/
...@@ -49,6 +52,12 @@ lobby[hidden], webview[hidden] { ...@@ -49,6 +52,12 @@ lobby[hidden], webview[hidden] {
overflow: hidden; overflow: hidden;
} }
/* 不加这个切到有 Webview 的页面,上面的圆角会消失 */
/* 即使加了这个,下面的圆角也会消失 */
webview {
overflow: hidden;
}
#navbar { #navbar {
background-color: #f7f7f9!important; background-color: #f7f7f9!important;
padding: 0; padding: 0;
...@@ -78,4 +87,8 @@ lobby[hidden], webview[hidden] { ...@@ -78,4 +87,8 @@ lobby[hidden], webview[hidden] {
margin: .2rem 0.4rem; margin: .2rem 0.4rem;
color: #a7a7a7; color: #a7a7a7;
font-size: 1.2rem; font-size: 1.2rem;
}
#navbar {
z-index: 100;
} }
\ No newline at end of file
/*:host {*/ :host {
/*display: none;*/ display: none;
/*}*/ }
\ No newline at end of file \ No newline at end of file
...@@ -93,98 +93,6 @@ label { ...@@ -93,98 +93,6 @@ label {
font-size: 15px; font-size: 15px;
} }
h2 {
font-size: 20px;
}
dt, dd {
font-size: 14px;
}
.panel {
border: 1px solid #eceeef;
border-radius: 6px;
background: rgba(255,255,255,.7);
padding: .8rem;
margin-bottom: 1rem;
}
table {
margin-bottom: 0;
}
table th, table td {
border-top: none;
font-size: 14px;
font-weight: normal;
}
/*.table-curved {*/
/*border-collapse: separate;*/
/*border: solid #ccc 1px;*/
/*border-radius: 6px;*/
/*border-left: 0px;*/
/*border-top: 0px;*/
/*}*/
/*.table-curved > thead:first-child > tr:first-child > th {*/
/*border-bottom: 0px;*/
/*border-top: solid #ccc 1px;*/
/*}*/
/*.table-curved td, .table-curved th {*/
/*border-left: 1px solid #ccc;*/
/*border-top: 1px solid #ccc;*/
/*}*/
/*.table-curved > :first-child > :first-child > :first-child {*/
/*border-radius: 6px 0 0 0;*/
/*}*/
/*.table-curved > :first-child > :first-child > :last-child {*/
/*border-radius: 0 6px 0 0;*/
/*}*/
/*.table-curved > :last-child > :last-child > :first-child {*/
/*border-radius: 0 0 0 6px;*/
/*}*/
/*.table-curved > :last-child > :last-child > :last-child {*/
/*border-radius: 0 0 6px 0;*/
/*}*/
#icon {
width: 128px;
height: 128px;
box-shadow: 0 0 4px #ccc;
}
#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;
position: relative;
}
#right {
margin-left: 1rem;
}
h1 {
font-size: 28px;
margin-bottom: 0;
}
#time {
font-size: 14px;
margin-bottom: .6rem;
}
#action {
margin-bottom: .5rem;
}
form { form {
margin-bottom: 0; margin-bottom: 0;
...@@ -195,22 +103,6 @@ form { ...@@ -195,22 +103,6 @@ form {
border-color: #008dbb; border-color: #008dbb;
} }
th { #action {
width: 25%; margin-bottom: .5rem;
}
.moreinfo {
color: #00a4d9;
display: block;
position: absolute;
top: 12px;
right: 18px;
font-size: 14px;
}
#arena {
position: relative;
}
select {
margin-right: 0 !important;
} }
\ No newline at end of file
<div id="main" class="panel"> <div id="action">
<img id="icon" class="rounded" src="https://raw.githubusercontent.com/mycard/ygopro/master/premake/gframe/ygopro.ico"> <button [disabled]="matching||!appsService.allReady(app)" (click)="request_match('athletic')" *ngIf="matching_arena != 'athletic'" type="button" class="btn btn-primary btn-sm">
<div id="right"> <i class="fa fa-play" aria-hidden="true"></i> <span i18n>竞技匹配</span></button>
<h1>{{currentApp.name}}</h1> <button i18n [disabled]="!appsService.allReady(app)" (click)="cancel_match()" *ngIf="matching_arena == 'athletic'" type="button" class="btn btn-primary btn-sm">取消等待</button>
<div id="time">您已玩了 2564 小时</div> <button i18n [disabled]="matching||!appsService.allReady(app)" (click)="request_match('entertain')" *ngIf="matching_arena != 'entertain'" type="button" class="btn btn-secondary btn-sm">娱乐匹配</button>
<div id="action"> <button i18n [disabled]="!appsService.allReady(app)" (click)="cancel_match()" *ngIf="matching_arena == 'entertain'" type="button" class="btn btn-secondary btn-sm">取消等待</button>
<button [disabled]="matching||!appsService.allReady(app)" (click)="request_match('athletic')" *ngIf="matching_arena != 'athletic'" type="button" class="btn btn-primary btn-sm"> <!--<button i18n [disabled]="matching||!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-modal">创建房间</button>-->
<i class="fa fa-play" aria-hidden="true"></i> <span i18n>竞技匹配</span></button> <button i18n [disabled]="matching||!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-list-modal">房间列表</button>
<button i18n [disabled]="!appsService.allReady(app)" (click)="cancel_match()" *ngIf="matching_arena == 'athletic'" type="button" class="btn btn-primary btn-sm">取消等待</button> <button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-windbot">单人模式</button>
<button i18n [disabled]="matching||!appsService.allReady(app)" (click)="request_match('entertain')" *ngIf="matching_arena != 'entertain'" type="button" class="btn btn-secondary btn-sm">娱乐匹配</button>
<button i18n [disabled]="!appsService.allReady(app)" (click)="cancel_match()" *ngIf="matching_arena == 'entertain'" type="button" class="btn btn-secondary btn-sm">取消等待</button>
<!--<button i18n [disabled]="matching||!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-modal">创建房间</button>-->
<button i18n [disabled]="matching||!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-list-modal">房间列表</button>
<button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-windbot">单人模式</button>
</div>
<form class="form-inline">
<div class="form-group">
<div class="input-group input-group-sm">
<label i18n class="input-group-addon" id="basic-addon1">卡组</label>
<select class="form-control mr-sm-2 form-control-sm" id="exampleSelect1" name="deck" [(ngModel)]="current_deck">
<option *ngFor="let deck of decks" [ngValue]="deck">{{deck}}</option>
</select>
<!--<input type="text" class="form-control" aria-label="Text input with checkbox">-->
<span class="input-group-btn">
<button i18n [disabled]="!appsService.allReady(app)" type="submit" class="btn btn-secondary mr-sm-2 btn-sm" (click)="edit_deck(current_deck)">编辑</button>
</span>
</div>
<!--< for="exampleSelect1" class="mr-sm-2"></>-->
</div>
<!--<button i18n [disabled]="!appsService.allReady(app)" type="submit" (click)="delete_deck(current_deck)" class="btn btn-secondary mr-sm-2 btn-sm">删除</button>-->
<!--<button i18n [disabled]="!appsService.allReady(app)" type="submit" (click)="refresh()" class="btn btn-secondary mr-sm-2 btn-sm">刷新</button>-->
</form>
</div>
</div>
<!--应用未安装-->
<div class="actions" *ngIf="!currentApp.isInstalled()">
<button i18n (click)="updateInstallOption(currentApp)" type="button" class="btn btn-primary" data-toggle="modal" data-target="#install-modal">安装</button>
<button i18n *ngIf="currentApp.runnable()" (click)="updateInstallOption(currentApp)" type="button" class="btn btn-secondary" data-toggle="modal" data-target="#import-modal">导入</button>
</div>
<!--应用变更中-->
<div class="actions" *ngIf="currentApp.isInstalled() && !currentApp.isReady()">
<div id="status">
<span i18n *ngIf="currentApp.isDownloading()">正在下载</span>
<span i18n *ngIf="currentApp.isInstalling()">正在安装...</span>
<span i18n *ngIf="currentApp.isUninstalling()">正在卸载...</span>
<span i18n *ngIf="currentApp.isWaiting()">等待安装...</span>
<span i18n *ngIf="currentApp.isUpdating()">正在更新...</span>
<span *ngIf="currentApp.status.total">{{(currentApp.status.progress/currentApp.status.total * 100).toFixed()}}%</span>
<span>{{currentApp.progressMessage()}}</span>
</div>
<progress class="progress" [class.progress-striped]="!currentApp.status.total" [class.progress-animated]="!currentApp.status.total" value="{{currentApp.status.total ? currentApp.status.progress : 1}}" max="{{currentApp.status.total}}"></progress>
</div>
<!--应用ready-->
<div class="actions" *ngIf="currentApp.isReady() && (currentApp.id != 'ygopro')">
<button i18n *ngIf="currentApp.runnable()" (click)="runApp(currentApp)" [disabled]="!appsService.allReady(currentApp)" type="button" class="btn btn-primary">运行</button>
<button i18n *ngIf="currentApp.runnable() && currentApp.actions.get('custom')" [disabled]="!appsService.allReady(currentApp)" (click)="custom(currentApp)" type="button" class="btn btn-secondary">设置</button>
<div id="network" *ngIf="currentApp.network && currentApp.network.protocol == 'maotama'">
<div class="input-group">
<input *ngIf="appsService.connections.get(currentApp)" [value]="appsService.connections.get(currentApp).address || 'Loading...'" readonly type="text" class="form-control" title="address">
<div class="input-group-btn" style="flex-direction: row">
<button i18n *ngIf="!appsService.connections.get(currentApp)" [disabled]="!appsService.allReady(currentApp)" (click)="appsService.network(currentApp, currentApp.network.servers[0])" type="button" class="btn btn-secondary">联机</button>
<button i18n *ngIf="appsService.connections.get(currentApp)" (click)="copy(appsService.connections.get(currentApp).address)" [disabled]="!appsService.connections.get(currentApp).address" type="button" class="btn btn-secondary">复制</button>
<button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" style="height: 38px;"></button>
<div class="dropdown-menu" [class.dropdown-menu-right]="appsService.connections.get(currentApp)">
<h6 i18n class="dropdown-header">选择服务器</h6>
<a *ngFor="let server of currentApp.network.servers" (click)="appsService.network(currentApp, server)" class="dropdown-item" href="#">{{server.id}}</a>
<div *ngIf="appsService.connections.get(currentApp)" class="dropdown-divider"></div>
<a i18n *ngIf="appsService.connections.get(currentApp)" (click)="appsService.connections.get(currentApp).connection.close()" class="dropdown-item" href="#">取消</a>
</div>
</div>
</div>
</div>
</div> </div>
<div class="input-group input-group-sm">
<label i18n class="input-group-addon" id="basic-addon1">卡组</label>
<!--<div class="panel">--> <select class="form-control form-control-sm" id="exampleSelect1" name="deck" [(ngModel)]="current_deck">
<option *ngFor="let deck of decks" [ngValue]="deck">{{deck}}</option>
<!--</div>--> </select>
<div class="actions"> <!--<input type="text" class="form-control" aria-label="Text input with checkbox">-->
<span class="input-group-btn">
<!--{"exp":1839,"exp_rank":"9","pt":2207.2901,"arena_rank":"30","win":"703","lose":"568","draw":5,"all":"1276","ratio":"55.09"}--> <button id="edit_deck_button" i18n [disabled]="!appsService.allReady(app)" class="btn btn-secondary btn-sm" (click)="edit_deck(current_deck)">编辑</button>
</span>
<div id="arena" class="panel panel-default" *ngIf="points">
<h2 i18n>排位成绩</h2>
<table class="table table-sm">
<tbody>
<tr>
<th>竞技排名</th>
<td>{{points.arena_rank}}</td>
<th>娱乐排名</th>
<td>{{points.exp_rank}}</td>
</tr>
<tr>
<th>竞技胜率</th>
<td>{{points.athletic_wl_ratio}}%</td>
<th>经验</th>
<td>{{points.exp}}</td>
</tr>
<tr>
<th>胜场</th>
<td>{{points.athletic_win}}</td>
<th>胜场</th>
<td>{{points.entertain_win}}</td>
</tr>
<tr>
<th>负场</th>
<td>{{points.entertain_lose}}</td>
<th>负场</th>
<td>{{points.entertain_lose}}</td>
</tr>
<tr>
<th>平局</th>
<td>{{points.athletic_draw}}</td>
<th>平局</th>
<td>{{points.entertain_draw}}</td>
</tr>
<tr>
<th>总场</th>
<td>{{points.athletic_all}}</td>
<th>总场</th>
<td>{{points.entertain_all}}</td>
</tr>
</tbody>
</table>
<a i18n href="https://mycard.moe/ygopro/arena/" target="_blank" class="moreinfo">更多资料</a>
</div>
<!--<div *ngIf="points" class="row">-->
<!--<dl class="col-4 row">-->
<!--<dt i18n class="col-8">竞技排名</dt>-->
<!--<dd class="col-4">{{points.arena_rank}}</dd>-->
<!--<dt i18n class="col-8">竞技胜率</dt>-->
<!--<dd class="col-4">{{points.athletic_wl_ratio}}%</dd>-->
<!--<dt i18n class="col-8">胜场</dt>-->
<!--<dd class="col-4">{{points.athletic_win}}</dd>-->
<!--<dt i18n class="col-8">负场</dt>-->
<!--<dd class="col-4">{{points.athletic_lose}}</dd>-->
<!--<dt i18n class="col-8">平局</dt>-->
<!--<dd class="col-4">{{points.athletic_draw}}</dd>-->
<!--<dt i18n class="col-8">总场</dt>-->
<!--<dd class="col-4">{{points.athletic_all}}</dd>-->
<!--</dl>-->
<!--<dl class="col-4 row">-->
<!--<dt i18n class="col-8">娱乐排名</dt>-->
<!--<dd class="col-4">{{points.exp_rank}}</dd>-->
<!--<dt i18n class="col-8">经验</dt>-->
<!--<dd class="col-4">{{points.exp}}</dd>-->
<!--<dt i18n class="col-8">胜场</dt>-->
<!--<dd class="col-4">{{points.entertain_win}}</dd>-->
<!--<dt i18n class="col-8">负场</dt>-->
<!--<dd class="col-4">{{points.entertain_lose}}</dd>-->
<!--<dt i18n class="col-8">平局</dt>-->
<!--<dd class="col-4">{{points.entertain_draw}}</dd>-->
<!--<dt i18n class="col-8">总场</dt>-->
<!--<dd class="col-4">{{points.entertain_all}}</dd>-->
<!--</dl>-->
<!--</div>-->
</div> </div>
<div class="modal fade" id="game-create-windbot" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade" id="game-create-windbot" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
......
/** /**
* Created by zh99998 on 16/9/2. * Created by zh99998 on 16/9/2.
*/ */
import {Component, OnInit, ChangeDetectorRef, Input} from '@angular/core'; import {Component, OnInit, ChangeDetectorRef, Input, EventEmitter, Output} from '@angular/core';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as child_process from 'child_process'; import * as child_process from 'child_process';
...@@ -71,7 +71,7 @@ interface Options { ...@@ -71,7 +71,7 @@ interface Options {
lflist?: number; lflist?: number;
time_limit?: number; time_limit?: number;
} }
interface Points { export interface Points {
exp: number; exp: number;
exp_rank: number; exp_rank: number;
pt: number; pt: number;
...@@ -102,12 +102,15 @@ export class YGOProComponent implements OnInit { ...@@ -102,12 +102,15 @@ export class YGOProComponent implements OnInit {
app: App; app: App;
@Input() @Input()
currentApp: App; currentApp: App;
@Output()
points: EventEmitter<Points> = new EventEmitter();
decks: string[] = []; decks: string[] = [];
current_deck: string; current_deck: string;
system_conf: string; system_conf: string;
numfont: string[]; numfont: string[];
textfont: string[]; textfont: string[];
points: Points; // points: Points;
windbot: string[]; // ["琪露诺", "谜之剑士LV4", "复制植物", "尼亚"]; windbot: string[]; // ["琪露诺", "谜之剑士LV4", "复制植物", "尼亚"];
...@@ -136,8 +139,8 @@ export class YGOProComponent implements OnInit { ...@@ -136,8 +139,8 @@ export class YGOProComponent implements OnInit {
matching: ISubscription | undefined; matching: ISubscription | undefined;
matching_arena: string | undefined; matching_arena: string | undefined;
constructor (private http: Http, private appsService: AppsService, private loginService: LoginService, constructor(private http: Http, private appsService: AppsService, private loginService: LoginService,
private settingsService: SettingsService, private ref: ChangeDetectorRef) { private settingsService: SettingsService, private ref: ChangeDetectorRef) {
switch (process.platform) { switch (process.platform) {
case 'darwin': case 'darwin':
this.numfont = ['/System/Library/Fonts/SFNSTextCondensed-Bold.otf']; this.numfont = ['/System/Library/Fonts/SFNSTextCondensed-Bold.otf'];
...@@ -174,7 +177,7 @@ export class YGOProComponent implements OnInit { ...@@ -174,7 +177,7 @@ export class YGOProComponent implements OnInit {
} }
async ngOnInit () { async ngOnInit() {
let locale: string; let locale: string;
if (this.settingsService.getLocale().startsWith('zh')) { if (this.settingsService.getLocale().startsWith('zh')) {
...@@ -232,7 +235,7 @@ export class YGOProComponent implements OnInit { ...@@ -232,7 +235,7 @@ export class YGOProComponent implements OnInit {
}); });
} }
async refresh () { async refresh() {
let decks = await this.get_decks(); let decks = await this.get_decks();
this.decks = decks; this.decks = decks;
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
...@@ -246,15 +249,16 @@ export class YGOProComponent implements OnInit { ...@@ -246,15 +249,16 @@ export class YGOProComponent implements OnInit {
let params = new URLSearchParams(); let params = new URLSearchParams();
params.set('username', this.loginService.user.username); params.set('username', this.loginService.user.username);
try { try {
this.points = await this.http.get('https://mycard.moe/ygopro/api/user', {search: params}) let points = await this.http.get('https://mycard.moe/ygopro/api/user', {search: params})
.map((response) => response.json()) .map((response) => response.json())
.toPromise(); .toPromise();
this.points.emit(points);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
}; };
get_decks (): Promise<string[]> { get_decks(): Promise<string[]> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.readdir(path.join(this.app.local!.path, 'deck'), (error, files) => { fs.readdir(path.join(this.app.local!.path, 'deck'), (error, files) => {
if (error) { if (error) {
...@@ -266,7 +270,7 @@ export class YGOProComponent implements OnInit { ...@@ -266,7 +270,7 @@ export class YGOProComponent implements OnInit {
}); });
} }
async get_font (files: string[]): Promise<string | undefined> { async get_font(files: string[]): Promise<string | undefined> {
for (let file of files) { for (let file of files) {
let found = await new Promise((resolve) => fs.access(file, fs.constants.R_OK, error => resolve(!error))); let found = await new Promise((resolve) => fs.access(file, fs.constants.R_OK, error => resolve(!error)));
if (found) { if (found) {
...@@ -275,14 +279,14 @@ export class YGOProComponent implements OnInit { ...@@ -275,14 +279,14 @@ export class YGOProComponent implements OnInit {
} }
} }
async delete_deck (deck: string) { async delete_deck(deck: string) {
if (confirm('确认删除?')) { if (confirm('确认删除?')) {
await new Promise(resolve => fs.unlink(path.join(this.app.local!.path, 'deck', deck + '.ydk'), resolve)); await new Promise(resolve => fs.unlink(path.join(this.app.local!.path, 'deck', deck + '.ydk'), resolve));
return this.refresh(); return this.refresh();
} }
} }
async fix_fonts (data: SystemConf) { async fix_fonts(data: SystemConf) {
if (!await this.get_font([data.numfont])) { if (!await this.get_font([data.numfont])) {
let font = await this.get_font(this.numfont); let font = await this.get_font(this.numfont);
if (font) { if (font) {
...@@ -298,7 +302,7 @@ export class YGOProComponent implements OnInit { ...@@ -298,7 +302,7 @@ export class YGOProComponent implements OnInit {
} }
}; };
load_system_conf (): Promise<SystemConf> { load_system_conf(): Promise<SystemConf> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.readFile(this.system_conf, {encoding: 'utf-8'}, (error, data) => { fs.readFile(this.system_conf, {encoding: 'utf-8'}, (error, data) => {
if (error) { if (error) {
...@@ -309,7 +313,7 @@ export class YGOProComponent implements OnInit { ...@@ -309,7 +313,7 @@ export class YGOProComponent implements OnInit {
}); });
}; };
save_system_conf (data: SystemConf) { save_system_conf(data: SystemConf) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.writeFile(this.system_conf, ini.unsafe(ini.stringify(data, <EncodeOptions>{whitespace: true})), (error) => { fs.writeFile(this.system_conf, ini.unsafe(ini.stringify(data, <EncodeOptions>{whitespace: true})), (error) => {
if (error) { if (error) {
...@@ -320,7 +324,7 @@ export class YGOProComponent implements OnInit { ...@@ -320,7 +324,7 @@ export class YGOProComponent implements OnInit {
}); });
}; };
async join (name: string, server: Server) { async join(name: string, server: Server) {
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf); await this.fix_fonts(system_conf);
system_conf.lastdeck = this.current_deck; system_conf.lastdeck = this.current_deck;
...@@ -333,7 +337,7 @@ export class YGOProComponent implements OnInit { ...@@ -333,7 +337,7 @@ export class YGOProComponent implements OnInit {
return this.start_game(['-j']); return this.start_game(['-j']);
}; };
async edit_deck (deck: string) { async edit_deck(deck: string) {
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf); await this.fix_fonts(system_conf);
system_conf.lastdeck = deck; system_conf.lastdeck = deck;
...@@ -341,11 +345,11 @@ export class YGOProComponent implements OnInit { ...@@ -341,11 +345,11 @@ export class YGOProComponent implements OnInit {
return this.start_game(['-d']); return this.start_game(['-d']);
} }
join_windbot (name: string) { join_windbot(name: string) {
return this.join('AI#' + name, this.servers[0]); return this.join('AI#' + name, this.servers[0]);
} }
async start_game (args: string[]) { async start_game(args: string[]) {
let win = remote.getCurrentWindow(); let win = remote.getCurrentWindow();
win.minimize(); win.minimize();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
...@@ -357,7 +361,7 @@ export class YGOProComponent implements OnInit { ...@@ -357,7 +361,7 @@ export class YGOProComponent implements OnInit {
reject(error); reject(error);
win.restore(); win.restore();
}); });
child.on('exit', async (code, signal) => { child.on('exit', async(code, signal) => {
// error 触发之后还可能会触发exit,但是Promise只承认首次状态转移,因此这里无需重复判断是否已经error过。 // error 触发之后还可能会触发exit,但是Promise只承认首次状态转移,因此这里无需重复判断是否已经error过。
await this.refresh(); await this.refresh();
resolve(); resolve();
...@@ -366,7 +370,7 @@ export class YGOProComponent implements OnInit { ...@@ -366,7 +370,7 @@ export class YGOProComponent implements OnInit {
}); });
}; };
create_room (room: Room) { create_room(room: Room) {
let options_buffer = new Buffer(6); let options_buffer = new Buffer(6);
// 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit // 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit
options_buffer.writeUInt8((room.private ? 2 : 1) << 4, 1); options_buffer.writeUInt8((room.private ? 2 : 1) << 4, 1);
...@@ -397,7 +401,7 @@ export class YGOProComponent implements OnInit { ...@@ -397,7 +401,7 @@ export class YGOProComponent implements OnInit {
this.join(password, this.servers[0]); this.join(password, this.servers[0]);
} }
join_room (room: Room) { join_room(room: Room) {
let options_buffer = new Buffer(6); let options_buffer = new Buffer(6);
options_buffer.writeUInt8(3 << 4, 1); options_buffer.writeUInt8(3 << 4, 1);
let checksum = 0; let checksum = 0;
...@@ -417,7 +421,7 @@ export class YGOProComponent implements OnInit { ...@@ -417,7 +421,7 @@ export class YGOProComponent implements OnInit {
this.join(password, room.server!); this.join(password, room.server!);
} }
request_match (arena = 'entertain') { request_match(arena = 'entertain') {
let headers = new Headers(); let headers = new Headers();
headers.append('Authorization', headers.append('Authorization',
'Basic ' + Buffer.from(this.loginService.user.username + ':' + this.loginService.user.external_id).toString('base64')); 'Basic ' + Buffer.from(this.loginService.user.username + ':' + this.loginService.user.external_id).toString('base64'));
...@@ -443,7 +447,7 @@ export class YGOProComponent implements OnInit { ...@@ -443,7 +447,7 @@ export class YGOProComponent implements OnInit {
}); });
} }
cancel_match () { cancel_match() {
this.matching!.unsubscribe(); this.matching!.unsubscribe();
this.matching = matching = undefined; this.matching = matching = undefined;
this.matching_arena = matching_arena = undefined; this.matching_arena = matching_arena = undefined;
......
...@@ -278,7 +278,7 @@ ...@@ -278,7 +278,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="19923836b1ae79614782426a7a001d8ccfa27b5c"> <trans-unit datatype="html" id="19923836b1ae79614782426a7a001d8ccfa27b5c">
<source>创建房间</source> <source>创建房间</source>
<target>Custom Game</target> <target>Create Game</target>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="c54a3c40a2766446dd03b0af75f64055aa404855"> <trans-unit datatype="html" id="c54a3c40a2766446dd03b0af75f64055aa404855">
......
{ {
"name": "mycard", "name": "mycard",
"version": "3.0.16", "version": "3.0.17",
"description": "mycard", "description": "mycard",
"keywords": [], "keywords": [],
"author": "zh99998 <zh99998@gmail.com>", "author": "zh99998 <zh99998@gmail.com>",
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
"candy-shop": "zh99998/candy-plugins#patch-5", "candy-shop": "zh99998/candy-plugins#patch-5",
"core-js": "latest", "core-js": "latest",
"electron-auto-updater": "latest", "electron-auto-updater": "latest",
"electron-cookies": "latest",
"electron-is-dev": "latest", "electron-is-dev": "latest",
"electron-sudo": "mycard/electron-sudo#mycard", "electron-sudo": "mycard/electron-sudo#mycard",
"font-awesome": "latest", "font-awesome": "latest",
......
html, body { html, body {
height: 100%; height: 100%;
overflow: hidden;
} }
body { body {
font-family: -apple-system, Arial, 'Source Sans Pro', "Microsoft YaHei", 'Microsoft JhengHei', "WenQuanYi Micro Hei", sans-serif; font-family: -apple-system, Arial, 'Source Sans Pro', "Microsoft YaHei", 'Microsoft JhengHei', "WenQuanYi Micro Hei", sans-serif;
-webkit-user-select: none;
background: transparent;
border-radius: 5px;
border: 1px solid #eee;
padding-right: 0 !important;
} }
mycard { mycard {
...@@ -85,6 +92,6 @@ body.resizing /deep/ * { ...@@ -85,6 +92,6 @@ body.resizing /deep/ * {
-webkit-user-select: none; -webkit-user-select: none;
} }
body { mycard {
-webkit-user-select: none; background-color: white;
} }
\ No newline at end of file
...@@ -73,7 +73,6 @@ System.config({ ...@@ -73,7 +73,6 @@ System.config({
"mkdirp": "@node/mkdirp", "mkdirp": "@node/mkdirp",
"aria2": "@node/aria2", "aria2": "@node/aria2",
"electron-sudo": "@node/electron-sudo", "electron-sudo": "@node/electron-sudo",
"electron-cookies": "@node/electron-cookies",
'jquery': 'npm:jquery/dist/jquery.min.js', 'jquery': 'npm:jquery/dist/jquery.min.js',
'tether': 'npm:tether/dist/js/tether.min.js', 'tether': 'npm:tether/dist/js/tether.min.js',
......
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