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

roomlist loading

parent 3572684b
......@@ -11,7 +11,8 @@ import {
MdGridListModule,
MdIconModule,
MdInputModule,
MdListModule, MdMenuModule,
MdListModule,
MdMenuModule, MdProgressSpinnerModule,
MdSelectModule,
MdSlideToggleModule,
MdSnackBarModule,
......@@ -21,18 +22,19 @@ import {
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import 'hammerjs';
import 'rxjs/Rx';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LobbyComponent } from './lobby/lobby.component';
import { MatchDialog } from './match/match.component';
import { NewRoomComponent } from './new-room/new-room.component';
import { ResultDialog } from './result/result.dialog';
import { RoomListComponent } from './room-list/room-list.component';
import { ToolbarComponent } from './toolbar/toolbar.component';
import { WatchComponent } from './watch/watch.component';
import { WindbotComponent } from './windbot/windbot.component';
import { YGOProService } from './ygopro.service';
import { ResultDialog } from './result/result.dialog';
@NgModule({
declarations: [
......@@ -69,7 +71,8 @@ import { ResultDialog } from './result/result.dialog';
MdAutocompleteModule,
ReactiveFormsModule,
JsonpModule,
MdMenuModule
MdMenuModule,
MdProgressSpinnerModule
],
providers: [YGOProService],
bootstrap: [AppComponent],
......
......@@ -23,6 +23,7 @@
<md-menu #menu="mdMenu">
<a [href]="login.logout()" md-menu-item>切换用户</a>
<button md-menu-item>大厅版本 {{version}}</button>
<button md-menu-item *ngIf="build">应用版本 {{build.version_name}}</button>
</md-menu>
</md-toolbar>
......@@ -158,7 +159,7 @@
<md-card-header>
<img *ngIf="item.image" md-card-avatar [src]="item.image">
<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>
</a>
</md-card>
......@@ -168,7 +169,7 @@
<md-card-header>
<img *ngIf="item.image_url" md-card-avatar [src]="item.image_url">
<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-header>
</a>
......
......@@ -3,8 +3,6 @@ import { FormControl } from '@angular/forms';
import { Http, Jsonp } from '@angular/http';
import { MdDialog } from '@angular/material';
import { ActivatedRoute } from '@angular/router';
// import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import { environment } from '../../environments/environment';
import { LoginService } from '../login.service';
import { MatchDialog } from '../match/match.component';
......@@ -20,6 +18,7 @@ import { YGOProService } from '../ygopro.service';
export class LobbyComponent {
version = environment.version;
build: BuildConfig;
searchCtrl = new FormControl();
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 {
arena_url.searchParams.set('sso', login.token);
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) {
......@@ -47,5 +54,10 @@ export class LobbyComponent {
request_match(arena: string) {
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 {
width: 20px;
height: 20px;
......@@ -7,11 +25,6 @@
.game-title {
flex: 2
}
:host {
display: flex;
flex-direction: column;
height: 100%;
}
md-table {
flex: 1;
......
<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">
<!--- Note that these columns can be defined in any order.
......
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 { 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 {
width: 20px;
height: 20px;
......
<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">
<!--- Note that these columns can be defined in any order.
......
......@@ -386,6 +386,10 @@ type Message =
export class RoomListDataSource extends DataSource<any> {
loading = true;
empty = false;
error: any;
constructor(private servers: Server[], private filter = 'waiting') {
super();
}
......@@ -394,35 +398,47 @@ export class RoomListDataSource extends DataSource<any> {
connect(): Observable<Room[]> {
return Observable.combineLatest(this.servers.map(server => {
const url = new URL(server.url!);
url.searchParams.set('filter', this.filter);
return Observable.webSocket({ url: url.toString() })
.scan((rooms: Room[], message: Message) => {
switch (message.event) {
case 'init':
return message.data.map(room => ({ server: server, ...room }));
case 'create':
return rooms.concat({ server: server, ...message.data });
case 'update':
Object.assign(rooms.find(room => room.id === message.data.id), message.data);
return rooms;
case 'delete':
return rooms.filter(room => room.id != message.data);
}
}, []);
}
), (...sources: Room[][]) => (<Room[]>[]).concat(...sources)).map(rooms => sortBy(rooms, (room) => {
if (room.arena === 'athletic') {
return 0;
} else if (room.arena === 'entertain') {
return 1;
} else if (room.id!.startsWith('AI#')) {
return 5;
} else {
return room.options.mode + 2;
}
})
);
const url = new URL(server.url!);
url.searchParams.set('filter', this.filter);
// 协议处理
return Observable.webSocket({ url: url.toString() })
.scan((rooms: Room[], message: Message) => {
switch (message.event) {
case 'init':
return message.data.map(room => ({ server: server, ...room }));
case 'create':
return rooms.concat({ server: server, ...message.data });
case 'update':
Object.assign(rooms.find(room => room.id === message.data.id), message.data);
return rooms;
case 'delete':
return rooms.filter(room => room.id != message.data);
}
}, []);
// 把多个服务器的数据拼接起来,这里是 combineLatest 的第二个参数
}), (...sources: Room[][]) => (<Room[]>[]).concat(...sources))
// 房间排序
.map(rooms => sortBy(rooms, (room) => {
if (room.arena === 'athletic') {
return 0;
} else if (room.arena === 'entertain') {
return 1;
} 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() {
......
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