Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Split Screen in the Frontend #121

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
class="mud-output doselect"
[style.background-color]="this.backgroundColor"
[style.color]="this.foregroundColor"
[style.overflow]="this.shallScroll ? 'auto' : 'hidden'"
>
<div class="mud-message" *ngFor="let mudLine of this.lines$ | async">
<app-mud-span [line]="mudLine"> </app-mud-span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
.mud-output {
flex: 0 1 100%;

overflow: auto;
overflow: hidden;
flex-direction: column;
flex-wrap: wrap;
font-family: monospace;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnDestroy,
Output,
ViewChild,
} from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
Expand All @@ -15,13 +18,18 @@ import { IMudMessage } from '../../types/mud-message';
templateUrl: './mud-output.component.html',
styleUrls: ['./mud-output.component.scss'],
})
export class MudOutputComponent implements AfterViewChecked, AfterViewInit {
export class MudOutputComponent
implements AfterViewChecked, AfterViewInit, OnDestroy
{
ngOnDestroy(): void {
console.log('DESTROY!');
}
private readonly linesSubject = new BehaviorSubject<IMudMessage[]>([]);

private canScrollToBottom = true;
private isScrollAtBottom = true;

@ViewChild('container', { static: true })
private readonly outputContainer!: ElementRef<HTMLDivElement>;
@ViewChild('container', { static: false })
private readonly outputContainer?: ElementRef<HTMLDivElement>;

protected readonly lines$: Observable<IMudMessage[]> =
this.linesSubject.asObservable();
Expand All @@ -41,16 +49,27 @@ export class MudOutputComponent implements AfterViewChecked, AfterViewInit {
@Input({ required: true })
public backgroundColor!: string;

@Input({ required: false })
public shallScroll: boolean = false;

@Input({ required: false })
public autoScroll: boolean = false;

@Output()
public readonly onScrolled = new EventEmitter<boolean>();

public ngAfterViewChecked() {
if (this.canScrollToBottom) {
if (this.isScrollAtBottom && this.autoScroll) {
this.scrollToBottom();
}
}

public ngAfterViewInit(): void {
this.outputContainer.nativeElement.onscroll = (event: Event) => {
this.onScroll(event);
};
if (this.outputContainer?.nativeElement !== undefined) {
this.outputContainer.nativeElement.onscroll = (event: Event) => {
this.onScroll(event);
};
}
}

private onScroll(event: Event): void {
Expand All @@ -61,11 +80,15 @@ export class MudOutputComponent implements AfterViewChecked, AfterViewInit {
element.scrollHeight - element.scrollTop - element.clientHeight,
) <= tolerance;

this.canScrollToBottom = atBottom;
this.onScrolled.emit(atBottom);

this.isScrollAtBottom = atBottom;
}

private scrollToBottom(): void {
this.outputContainer.nativeElement.scrollTop =
this.outputContainer.nativeElement.scrollHeight;
public scrollToBottom(): void {
if (this.outputContainer?.nativeElement !== undefined) {
this.outputContainer.nativeElement.scrollTop =
this.outputContainer.nativeElement.scrollHeight;
}
}
}
80 changes: 60 additions & 20 deletions frontend/src/app/core/mud/mud-client/mud-client.component.html
Original file line number Diff line number Diff line change
@@ -1,23 +1,63 @@
<app-mud-output
*ngIf="this.output$ | async as lines"
[lines]="lines"
[foregroundColor]="this.v.stdfg"
[backgroundColor]="this.v.stdbg"
></app-mud-output>
<ng-container *ngIf="this.mode$ | async as mode">
<p-splitter
*ngIf="mode === 'split'; else singleMode"
layout="vertical"
[style]="{ flex: '0 1 100%', overflow: 'hidden' }"
[panelStyle]="{ overflow: 'hidden' }"
[panelSizes]="[85, 15]"
>
<ng-template pTemplate>
<app-mud-output
id="test"
*ngIf="this.output$ | async as lines"
[lines]="lines"
[foregroundColor]="this.v.stdfg"
[backgroundColor]="this.v.stdbg"
[shallScroll]="true"
></app-mud-output>
</ng-template>
<ng-template pTemplate>
<app-mud-output
#mainOutputSplit
*ngIf="this.output$ | async as lines"
[lines]="lines"
[foregroundColor]="this.v.stdfg"
[backgroundColor]="this.v.stdbg"
[autoScroll]="true"
></app-mud-output>
</ng-template>
</p-splitter>

<ng-container *ngIf="this.isConnected$ | async; else disconnected">
<app-mud-input
[mode]="(this.showEcho$ | async) ? 'text' : 'password'"
(messageSent)="onInputReceived($event)"
></app-mud-input>
</ng-container>
<ng-template #singleMode>
<app-mud-output
*ngIf="this.output$ | async as lines"
[lines]="lines"
[foregroundColor]="this.v.stdfg"
[backgroundColor]="this.v.stdbg"
[autoScroll]="true"
[shallScroll]="true"
></app-mud-output>
</ng-template>

<ng-template #disconnected>
<div id="disconnected-panel">
<p>Disconnected!</p>
<p-button label="reconnect" (click)="this.onConnectClicked()"></p-button>
</div>
</ng-template>
<ng-container *ngIf="this.isConnected$ | async; else disconnected">
<div style="display: flex; align-items: center">
<app-mud-input
[mode]="(this.showEcho$ | async) ? 'text' : 'password'"
(messageSent)="onInputReceived($event)"
[style]="{ flex: '1 1 auto' }"
></app-mud-input>
<p-button
[style]="{ flex: '0 1 auto' }"
[label]="mode === 'normal' ? 'split' : 'unsplit'"
(click)="this.onSplitToggle()"
></p-button>
</div>
</ng-container>

<!--<p-divider layout="vertical"></p-divider>
<app-inventory [inv]="invlist" [vheight]="v.ref_height"></app-inventory>-->
<ng-template #disconnected>
<div id="disconnected-panel">
<p>Disconnected!</p>
<p-button label="reconnect" (click)="this.onConnectClicked()"></p-button>
</div>
</ng-template>
</ng-container>
23 changes: 19 additions & 4 deletions frontend/src/app/core/mud/mud-client/mud-client.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,31 @@
:host {
display: flex;
flex-direction: column;
flex: 1 0 100%;
overflow: hidden;
flex: 0 0 100%;
overflow: auto;

app-mud-menu {
flex: 0 1 auto;
}

p-splitter {
flex: 0 1 100%;
overflow: auto;
display: flex;
flex-direction: column;

.p-splitter {
flex: 1 1 100%;
}
}

app-mud-output {
flex: 1 1 auto;
overflow-y: auto;
flex: 1 1 100%;
overflow: hidden;

&#test {
flex: 1 1 0%;
}
}

app-mud-input {
Expand Down
34 changes: 31 additions & 3 deletions frontend/src/app/core/mud/mud-client/mud-client.component.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import { Component, HostListener, ViewChild } from '@angular/core';
import { Observable } from 'rxjs';
import {
AfterViewChecked,
Component,
HostListener,
ViewChild,
} from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

import { MudInputComponent } from '../components/mud-input/mud-input.component';
import { MudService } from '../mud.service';
import { IMudMessage } from '../types/mud-message';
import { isSecureString, SecureString } from '@mudlet3/frontend/shared';
import { MudOutputComponent } from 'src/app/core/mud/components/mud-output/mud-output.component';

@Component({
selector: 'app-mud-client',
templateUrl: './mud-client.component.html',
styleUrls: ['./mud-client.component.scss'],
})
export class MudclientComponent {
export class MudclientComponent implements AfterViewChecked {
private readonly mode = new BehaviorSubject<'normal' | 'split'>('normal');

protected readonly output$: Observable<IMudMessage[]>;

protected readonly isConnected$: Observable<boolean>;
protected readonly showEcho$: Observable<boolean>;

protected readonly mode$ = this.mode.asObservable();

@ViewChild(MudInputComponent, { static: false })
private mudInputComponent?: MudInputComponent;

@ViewChild('mainOutputSplit', { static: false })
private mudOutputComponent?: MudOutputComponent;

public v = {
// scrollLock: true,
// sizeCalculated: false,
Expand Down Expand Up @@ -52,6 +65,12 @@ export class MudclientComponent {

this.mudService.connect();

// this.mode$.subscribe((mode) => {
// if (mode === 'split') {
// this.mudOutputComponent?.scrollToBottom();
// }
// });

// this.invlist = new InventoryList();

// Todo[myst]: Herausfinden, was der cookieService alles unter 'mudcolors' gespeichert hat
Expand All @@ -67,11 +86,20 @@ export class MudclientComponent {
// this.v.stdbg = 'black';
// }
}
ngAfterViewChecked(): void {
if (this.mode.value === 'split') {
this.mudOutputComponent?.scrollToBottom();
}
}

// protected onDisconnectClicked() {
// this.mudService.disconnect();
// }

protected onSplitToggle() {
this.mode.next(this.mode.value === 'normal' ? 'split' : 'normal');
}

protected onConnectClicked() {
this.mudService.connect();
}
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/app/core/mud/mud.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { MudOutputComponent } from './components/mud-output/mud-output.component
import { MudspanComponent } from './components/mud-span/mud-span.component';
import { MudclientComponent } from './mud-client/mud-client.component';

import { SplitterModule } from 'primeng/splitter';

const primeModules = [SplitterModule];

@NgModule({
declarations: [
MudclientComponent,
Expand All @@ -28,6 +32,7 @@ import { MudclientComponent } from './mud-client/mud-client.component';
ReactiveFormsModule,
WidgetsModule,
MenuModule,
primeModules,
],
exports: [MudclientComponent],
})
Expand Down
Loading