Commit 26800575 authored by 神楽坂玲奈's avatar 神楽坂玲奈

roomlist loading

parent 3572684b
...@@ -11,7 +11,8 @@ import { ...@@ -11,7 +11,8 @@ import {
MdGridListModule, MdGridListModule,
MdIconModule, MdIconModule,
MdInputModule, MdInputModule,
MdListModule, MdMenuModule, MdListModule,
MdMenuModule, MdProgressSpinnerModule,
MdSelectModule, MdSelectModule,
MdSlideToggleModule, MdSlideToggleModule,
MdSnackBarModule, MdSnackBarModule,
...@@ -21,18 +22,19 @@ import { ...@@ -21,18 +22,19 @@ import {
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import 'hammerjs'; import 'hammerjs';
import 'rxjs/Rx';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { LobbyComponent } from './lobby/lobby.component'; import { LobbyComponent } from './lobby/lobby.component';
import { MatchDialog } from './match/match.component'; import { MatchDialog } from './match/match.component';
import { NewRoomComponent } from './new-room/new-room.component'; import { NewRoomComponent } from './new-room/new-room.component';
import { ResultDialog } from './result/result.dialog';
import { RoomListComponent } from './room-list/room-list.component'; import { RoomListComponent } from './room-list/room-list.component';
import { ToolbarComponent } from './toolbar/toolbar.component'; import { ToolbarComponent } from './toolbar/toolbar.component';
import { WatchComponent } from './watch/watch.component'; import { WatchComponent } from './watch/watch.component';
import { WindbotComponent } from './windbot/windbot.component'; import { WindbotComponent } from './windbot/windbot.component';
import { YGOProService } from './ygopro.service'; import { YGOProService } from './ygopro.service';
import { ResultDialog } from './result/result.dialog';
@NgModule({ @NgModule({
declarations: [ declarations: [
...@@ -69,7 +71,8 @@ import { ResultDialog } from './result/result.dialog'; ...@@ -69,7 +71,8 @@ import { ResultDialog } from './result/result.dialog';
MdAutocompleteModule, MdAutocompleteModule,
ReactiveFormsModule, ReactiveFormsModule,
JsonpModule, JsonpModule,
MdMenuModule MdMenuModule,
MdProgressSpinnerModule
], ],
providers: [YGOProService], providers: [YGOProService],
bootstrap: [AppComponent], bootstrap: [AppComponent],
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
<md-menu #menu="mdMenu"> <md-menu #menu="mdMenu">
<a [href]="login.logout()" md-menu-item>切换用户</a> <a [href]="login.logout()" md-menu-item>切换用户</a>
<button md-menu-item>大厅版本 {{version}}</button> <button md-menu-item>大厅版本 {{version}}</button>
<button md-menu-item *ngIf="build">应用版本 {{build.version_name}}</button>
</md-menu> </md-menu>
</md-toolbar> </md-toolbar>
...@@ -158,7 +159,7 @@ ...@@ -158,7 +159,7 @@
<md-card-header> <md-card-header>
<img *ngIf="item.image" md-card-avatar [src]="item.image"> <img *ngIf="item.image" md-card-avatar [src]="item.image">
<md-card-title>{{item.title}}</md-card-title> <md-card-title>{{item.title}}</md-card-title>
<md-card-subtitle>{{item.updated_at | date:"mediumDate"}}</md-card-subtitle> <md-card-subtitle>{{item.updated_at | date}}</md-card-subtitle>
</md-card-header> </md-card-header>
</a> </a>
</md-card> </md-card>
...@@ -168,7 +169,7 @@ ...@@ -168,7 +169,7 @@
<md-card-header> <md-card-header>
<img *ngIf="item.image_url" md-card-avatar [src]="item.image_url"> <img *ngIf="item.image_url" md-card-avatar [src]="item.image_url">
<md-card-title>{{item.title}}</md-card-title> <md-card-title>{{item.title}}</md-card-title>
<md-card-subtitle>by {{item.last_poster_username}} / {{item.last_posted_at | date:"mediumDate"}} <md-card-subtitle>by {{item.last_poster_username}} / {{item.last_posted_at | date}}
</md-card-subtitle> </md-card-subtitle>
</md-card-header> </md-card-header>
</a> </a>
......
...@@ -3,8 +3,6 @@ import { FormControl } from '@angular/forms'; ...@@ -3,8 +3,6 @@ import { FormControl } from '@angular/forms';
import { Http, Jsonp } from '@angular/http'; import { Http, Jsonp } from '@angular/http';
import { MdDialog } from '@angular/material'; import { MdDialog } from '@angular/material';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
// import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
import { LoginService } from '../login.service'; import { LoginService } from '../login.service';
import { MatchDialog } from '../match/match.component'; import { MatchDialog } from '../match/match.component';
...@@ -20,6 +18,7 @@ import { YGOProService } from '../ygopro.service'; ...@@ -20,6 +18,7 @@ import { YGOProService } from '../ygopro.service';
export class LobbyComponent { export class LobbyComponent {
version = environment.version; version = environment.version;
build: BuildConfig;
searchCtrl = new FormControl(); searchCtrl = new FormControl();
suggestion = this.searchCtrl.valueChanges.filter(name => name).flatMap(name => this.jsonp.get('http://www.ourocg.cn/Suggest.aspx', { suggestion = this.searchCtrl.valueChanges.filter(name => name).flatMap(name => this.jsonp.get('http://www.ourocg.cn/Suggest.aspx', {
...@@ -36,6 +35,14 @@ export class LobbyComponent { ...@@ -36,6 +35,14 @@ export class LobbyComponent {
arena_url.searchParams.set('sso', login.token); arena_url.searchParams.set('sso', login.token);
this.arena_url = arena_url.toString(); this.arena_url = arena_url.toString();
const matched = navigator.userAgent.match(/YGOMobile\/(.+?) \((.+?) (\d+)\)/);
if (matched) {
this.build = {
version_name: matched[1],
application_id: matched[2],
version_code: parseInt(matched[3])
};
}
} }
search(key: string) { search(key: string) {
...@@ -47,5 +54,10 @@ export class LobbyComponent { ...@@ -47,5 +54,10 @@ export class LobbyComponent {
request_match(arena: string) { request_match(arena: string) {
this.dialog.open(MatchDialog, { data: arena, disableClose: true }); this.dialog.open(MatchDialog, { data: arena, disableClose: true });
} }
}
interface BuildConfig {
version_name: string;
version_code: number;
application_id: string;
} }
:host {
display: flex;
flex-direction: column;
height: 100%;
}
.hint {
position: absolute;
top: 0;
left: 0;
bottom: 56px;
right: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.avatar { .avatar {
width: 20px; width: 20px;
height: 20px; height: 20px;
...@@ -7,11 +25,6 @@ ...@@ -7,11 +25,6 @@
.game-title { .game-title {
flex: 2 flex: 2
} }
:host {
display: flex;
flex-direction: column;
height: 100%;
}
md-table { md-table {
flex: 1; flex: 1;
......
<app-toolbar>房间列表</app-toolbar> <app-toolbar>房间列表</app-toolbar>
<div class="hint" *ngIf="dataSource.loading"><md-spinner></md-spinner></div>
<div class="hint" *ngIf="dataSource.empty">现在没有等待中的游戏,可以自行创建一个房间或者去匹配</div>
<div class="hint" *ngIf="dataSource.error">网络错误</div>
<md-table #table [dataSource]="dataSource"> <md-table #table [dataSource]="dataSource">
<!--- Note that these columns can be defined in any order. <!--- Note that these columns can be defined in any order.
......
import { ChangeDetectorRef, Component } from '@angular/core'; import { ChangeDetectorRef, Component } from '@angular/core';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/startWith';
import 'rxjs/Rx';
import { LoginService } from '../login.service'; import { LoginService } from '../login.service';
import { RoomListDataSource, YGOProService } from '../ygopro.service'; import { RoomListDataSource, YGOProService } from '../ygopro.service';
......
:host {
display: flex;
flex-direction: column;
height: 100%;
}
.hint {
position: absolute;
top: 0;
left: 0;
bottom: 56px;
right: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.avatar { .avatar {
width: 20px; width: 20px;
height: 20px; height: 20px;
......
<app-toolbar>观战</app-toolbar> <app-toolbar>观战</app-toolbar>
<div class="hint" *ngIf="dataSource.loading"><md-spinner></md-spinner></div>
<div class="hint" *ngIf="dataSource.empty">现在没有进行中的游戏</div>
<div class="hint" *ngIf="dataSource.error">网络错误</div>
<md-table #table [dataSource]="dataSource"> <md-table #table [dataSource]="dataSource">
<!--- Note that these columns can be defined in any order. <!--- Note that these columns can be defined in any order.
......
...@@ -386,6 +386,10 @@ type Message = ...@@ -386,6 +386,10 @@ type Message =
export class RoomListDataSource extends DataSource<any> { export class RoomListDataSource extends DataSource<any> {
loading = true;
empty = false;
error: any;
constructor(private servers: Server[], private filter = 'waiting') { constructor(private servers: Server[], private filter = 'waiting') {
super(); super();
} }
...@@ -394,35 +398,47 @@ export class RoomListDataSource extends DataSource<any> { ...@@ -394,35 +398,47 @@ export class RoomListDataSource extends DataSource<any> {
connect(): Observable<Room[]> { connect(): Observable<Room[]> {
return Observable.combineLatest(this.servers.map(server => { return Observable.combineLatest(this.servers.map(server => {
const url = new URL(server.url!); const url = new URL(server.url!);
url.searchParams.set('filter', this.filter); url.searchParams.set('filter', this.filter);
return Observable.webSocket({ url: url.toString() }) // 协议处理
.scan((rooms: Room[], message: Message) => { return Observable.webSocket({ url: url.toString() })
switch (message.event) { .scan((rooms: Room[], message: Message) => {
case 'init': switch (message.event) {
return message.data.map(room => ({ server: server, ...room })); case 'init':
case 'create': return message.data.map(room => ({ server: server, ...room }));
return rooms.concat({ server: server, ...message.data }); case 'create':
case 'update': return rooms.concat({ server: server, ...message.data });
Object.assign(rooms.find(room => room.id === message.data.id), message.data); case 'update':
return rooms; Object.assign(rooms.find(room => room.id === message.data.id), message.data);
case 'delete': return rooms;
return rooms.filter(room => room.id != message.data); case 'delete':
} return rooms.filter(room => room.id != message.data);
}, []); }
} }, []);
), (...sources: Room[][]) => (<Room[]>[]).concat(...sources)).map(rooms => sortBy(rooms, (room) => { // 把多个服务器的数据拼接起来,这里是 combineLatest 的第二个参数
if (room.arena === 'athletic') { }), (...sources: Room[][]) => (<Room[]>[]).concat(...sources))
return 0; // 房间排序
} else if (room.arena === 'entertain') { .map(rooms => sortBy(rooms, (room) => {
return 1; if (room.arena === 'athletic') {
} else if (room.id!.startsWith('AI#')) { return 0;
return 5; } else if (room.arena === 'entertain') {
} else { return 1;
return room.options.mode + 2; } else if (room.id!.startsWith('AI#')) {
} return 5;
}) } else {
); return room.options.mode + 2;
}
})
// loading、empty、error
).filter((rooms) => {
this.loading = false;
this.empty = rooms.length == 0;
return true;
}).catch((error) => {
this.loading = false;
this.error = error;
return [];
});
} }
disconnect() { disconnect() {
......
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