Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
cfx-ui: server list performance improvements
  • Loading branch information
blattersturm committed Jul 4, 2019
1 parent 16f7504 commit e5ea040
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 66 deletions.
Expand Up @@ -25,26 +25,46 @@ export class ServerTagFilterComponent implements OnInit, OnChanges, OnDestroy {
@Output()
public tagsChanged = new EventEmitter<ServerTags>();

get tags(): ServerTag[] {
tags: ServerTag[] = [];

serverTags: {[addr: string]: string[]} = {};

constructor(private serversService: ServersService) {
this.serversService
.getReplayedServers()
.filter(server => !!server)
.subscribe(server => {
this.addFilterIndex(server);
});

this.serversService
.getReplayedServers()
.bufferTime(500)
.subscribe(server => {
this.updateTagList();
});
}

private updateTagList() {
const tagList = Object.entries(
Object.values(this.serverTags)
.reduce<{[k: string]: number}>((acc: {[k: string]: number}, val: string[]) => {
for (const str of val) {
if (!acc.hasOwnProperty(str)) {
acc[str] = 0;
}

acc[str]++;
Object.values(this.serverTags)
.reduce<{[k: string]: number}>((acc: {[k: string]: number}, val: string[]) => {
for (const str of val) {
if (!acc.hasOwnProperty(str)) {
acc[str] = 0;
}
return acc;
}, {})
)
.map(([name, count]) => {
return {
name,
count

acc[str]++;
}
});
return acc;
}, {})
)
.map(([name, count]) => {
return {
name,
count
}
});

tagList.sort((a, b) => {
if (a.count === b.count) {
Expand All @@ -56,18 +76,7 @@ export class ServerTagFilterComponent implements OnInit, OnChanges, OnDestroy {
}
});

return tagList.slice(0, 50);
}

serverTags: {[addr: string]: string[]} = {};

constructor(private serversService: ServersService) {
this.serversService
.getReplayedServers()
.filter(server => !!server)
.subscribe(server => {
this.addFilterIndex(server);
});
this.tags = tagList.slice(0, 50);
}

private addFilterIndex(server: Server) {
Expand Down
@@ -1,7 +1,7 @@
import { Component, OnInit, PLATFORM_ID, Inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { Server, ServerIcon, PinConfig } from '../server';
import { Server, ServerIcon, PinConfigCached } from '../server';
import { ServersService } from '../servers.service';
import { ServerFilters, ServerFilterContainer, ServerTags } from './server-filter.component';

Expand All @@ -25,7 +25,7 @@ export class ServersContainerComponent implements OnInit {
localServers: Server[]; // temp value
icons: ServerIcon[];

pinConfig: PinConfig;
pinConfig: PinConfigCached;

filters: ServerFilterContainer;

Expand All @@ -34,7 +34,7 @@ export class ServersContainerComponent implements OnInit {
constructor(private serverService: ServersService, private gameService: GameService, private route: ActivatedRoute,
@Inject(PLATFORM_ID) private platformId: any) {
this.filters = new ServerFilterContainer();
this.pinConfig = new PinConfig();
this.pinConfig = new PinConfigCached(null);
}

serversArray: Server[] = [];
Expand All @@ -61,7 +61,7 @@ export class ServersContainerComponent implements OnInit {

loadServers() {
this.serverService.loadPinConfig()
.then(pinConfig => this.pinConfig = pinConfig);
.then(pinConfig => this.pinConfig = new PinConfigCached(pinConfig));


const typedServers = this.serverService
Expand Down
Expand Up @@ -8,8 +8,11 @@
<virtual-scroller
#scroll
[items]="sortedServers"
[bufferAmount]="15"
[bufferAmount]="25"
[stripedTable]="true"
[executeRefreshOutsideAngularZone]="true"
[scrollThrottlingTime]="100"
(vsUpdate)="changeDetectorRef.detectChanges()"
>
<div class="dummy"></div>
<servers-list-item
Expand Down
75 changes: 43 additions & 32 deletions ext/cfx-ui/src/app/servers/components/servers-list.component.ts
@@ -1,5 +1,5 @@
import { Component, OnInit, OnChanges, Input, NgZone, Inject, PLATFORM_ID } from '@angular/core';
import { Server, PinConfig } from '../server';
import { Component, OnInit, OnChanges, Input, NgZone, Inject, PLATFORM_ID, ChangeDetectorRef } from '@angular/core';
import { Server, PinConfigCached } from '../server';
import { ServersListHeadingColumn } from './servers-list-header.component';
import { ServerFilterContainer } from './server-filter.component';
import { Subject } from 'rxjs/Subject';
Expand All @@ -24,18 +24,21 @@ export class ServersListComponent implements OnInit, OnChanges {
private filters: ServerFilterContainer;

@Input()
private pinConfig: PinConfig;
private pinConfig: PinConfigCached;

private subscriptions: { [addr: string]: any } = {};

private lastLength: number;

sortOrder: string[];

columns: ServersListHeadingColumn[];

localServers: Server[];
sortedServers: Server[];

constructor(private zone: NgZone, @Inject(LocalStorage) private localStorage: any, @Inject(PLATFORM_ID) private platformId: any) {
constructor(private zone: NgZone, @Inject(LocalStorage) private localStorage: any, @Inject(PLATFORM_ID) private platformId: any,
public changeDetectorRef: ChangeDetectorRef) {
this.servers = [];

this.columns = [
Expand Down Expand Up @@ -83,6 +86,12 @@ export class ServersListComponent implements OnInit, OnChanges {
if (changed) {
changed = false;

for (const server of (this.servers || [])) {
if (!this.subscriptions[server.address]) {
this.subscriptions[server.address] = server.onChanged.subscribe(a => this.changeSubject.next());
}
}

zone.run(() => {
this.sortAndFilterServers();
});
Expand All @@ -100,7 +109,7 @@ export class ServersListComponent implements OnInit, OnChanges {
return false;
}

return (this.pinConfig.pinnedServers.indexOf(server.address) >= 0)
return this.pinConfig.pinnedServers.has(server.address);
}

isPremium(server: Server) {
Expand Down Expand Up @@ -213,7 +222,9 @@ export class ServersListComponent implements OnInit, OnChanges {
const filters = filterList.filters;

const hiddenByTags = (server: Server) => {
if (filterList.tags) {
const tagListEntries = (filterList.tags) ? Object.entries(filterList.tags.tagList) : [];

if (tagListEntries.length > 0) {
const tags =
(server && server.data && server.data.vars && server.data.vars.tags) ?
(<string>server.data.vars.tags)
Expand All @@ -225,7 +236,7 @@ export class ServersListComponent implements OnInit, OnChanges {

const tagSet = new Set<string>(tags);

for (const [ tag, active ] of Object.entries(filterList.tags.tagList)) {
for (const [ tag, active ] of tagListEntries) {
if (active) {
if (!tagSet.has(tag)) {
return true;
Expand All @@ -247,7 +258,7 @@ export class ServersListComponent implements OnInit, OnChanges {
}

if (server.currentPlayers === 0 && filters.hideEmpty) {
if (!this.isPinned(server) || !this.pinConfig.pinIfEmpty) {
if (!this.isPinned(server) || !this.pinConfig.data.pinIfEmpty) {
return false;
}
}
Expand All @@ -271,7 +282,7 @@ export class ServersListComponent implements OnInit, OnChanges {
}

sortAndFilterServers() {
const servers = (this.servers || []).concat().filter(this.getFilter(this.filters));
const servers = (this.servers || []).filter(this.getFilter(this.filters));

const sortChain = (a: Server, b: Server, ...stack: ((a: Server, b: Server) => number)[]) => {
for (const entry of stack) {
Expand Down Expand Up @@ -311,26 +322,30 @@ export class ServersListComponent implements OnInit, OnChanges {
}
};

const sortList = [
(a: Server, b: Server) => {
const aPinned = this.isPinned(a);
const bPinned = this.isPinned(b);

if (aPinned === bPinned) {
return 0;
} else if (aPinned && !bPinned) {
return -1;
} else if (!aPinned && bPinned) {
return 1;
}
},
sortSortable(this.sortOrder),
sortSortable(['upvotePower', '-']),
sortSortable(['ping', '+']),
sortSortable(['name', '+'])
];

servers.sort((a, b) => {
return sortChain(
a,
b,
(a: Server, b: Server) => {
const aPinned = this.isPinned(a);
const bPinned = this.isPinned(b);

if (aPinned === bPinned) {
return 0;
} else if (aPinned && !bPinned) {
return -1;
} else if (!aPinned && bPinned) {
return 1;
}
},
sortSortable(this.sortOrder),
sortSortable(['upvotePower', '-']),
sortSortable(['ping', '+']),
sortSortable(['name', '+'])
...sortList
);
});

Expand Down Expand Up @@ -358,14 +373,10 @@ export class ServersListComponent implements OnInit, OnChanges {
changeObservable = this.changeSubject.asObservable();

ngOnChanges() {
for (const server of (this.servers || [])) {
if (!this.subscriptions[server.address]) {
this.subscriptions[server.address] = server.onChanged.subscribe(a => this.changeSubject.next());
}
if (this.servers.length !== this.lastLength) {
this.changeSubject.next();
this.lastLength = this.servers.length;
}

//this.sortAndFilterServers();
this.changeSubject.next();
}

svTrack(index: number, serverRow: Server) {
Expand Down
15 changes: 15 additions & 0 deletions ext/cfx-ui/src/app/servers/server.ts
Expand Up @@ -128,4 +128,19 @@ export class PinConfig {
pinIfEmpty = false;

pinnedServers: string[] = [];
}

export class PinConfigCached {
public data: PinConfig;
public pinnedServers: Set<string>;

constructor(pinConfig: PinConfig) {
if (pinConfig) {
this.data = pinConfig;
} else {
this.data = new PinConfig();
}

this.pinnedServers = new Set<string>(this.data.pinnedServers);
}
}

0 comments on commit e5ea040

Please sign in to comment.