206 lines
5.3 KiB
TypeScript
206 lines
5.3 KiB
TypeScript
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
|
import { WebSocketService } from '../services/websocket.service';
|
|
import { WebSocketMessage } from '../message-types/websocket-message';
|
|
import { IDEMessage } from '../message-types/ide-message';
|
|
import { DeployMessage } from '../message-types/deploy-message';
|
|
import { DeploymentNotificationService } from '../services/deployment-notification.service';
|
|
import { IdeConfigService } from '../services/config.service';
|
|
import { LanguageMap } from './language-map';
|
|
import { first } from 'rxjs/operators';
|
|
|
|
enum DeployButtonState {
|
|
DEPLOYED,
|
|
DEPLOYING,
|
|
FAILED,
|
|
TODEPLOY
|
|
}
|
|
|
|
enum CodeState {
|
|
SAVED,
|
|
DIRTY
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-ide',
|
|
templateUrl: './ide.component.html',
|
|
styleUrls: ['./ide.component.scss']
|
|
})
|
|
export class IdeComponent implements OnInit {
|
|
CodeState = CodeState;
|
|
DeployButtonState = DeployButtonState;
|
|
|
|
files: string[];
|
|
filename = '';
|
|
lastFilename = '';
|
|
reloadFile = false;
|
|
code = 'Loading your file...';
|
|
|
|
codeState = CodeState.SAVED;
|
|
deployButtonState = DeployButtonState.DEPLOYED;
|
|
deployButtonText = this.configService.deployButtonText;
|
|
showDeployButton = this.configService.showDeployButton;
|
|
autosave = null;
|
|
|
|
editorOptions = {
|
|
theme: 'vs-dark',
|
|
language: 'text',
|
|
glyphMargin: false,
|
|
minimap: {enabled: false}
|
|
};
|
|
|
|
command_handlers = {
|
|
'ide.reload': this.reloadHandler.bind(this),
|
|
'ide.read': this.readHandler.bind(this),
|
|
'ide.write': this.writeHandler.bind(this),
|
|
};
|
|
|
|
constructor(private webSocketService: WebSocketService,
|
|
private changeDetectorRef: ChangeDetectorRef,
|
|
private deploymentNotificationService: DeploymentNotificationService,
|
|
private configService: IdeConfigService) {}
|
|
|
|
ngOnInit() {
|
|
this.webSocketService.connect();
|
|
this.configService.init();
|
|
this.subscribeWS();
|
|
this.subscribeFirstLanguageDetection();
|
|
this.requestCode();
|
|
this.resetAutoSaveCountdown();
|
|
}
|
|
|
|
subscribeWS() {
|
|
this.webSocketService.observeControl<WebSocketMessage>('ide').subscribe(message => {
|
|
this.command_handlers[message.key](message);
|
|
this.changeDetectorRef.detectChanges();
|
|
});
|
|
|
|
this.webSocketService.observeControl<DeployMessage>('deploy.finish').subscribe(
|
|
message => this.deployHandler(message)
|
|
);
|
|
}
|
|
|
|
subscribeFirstLanguageDetection() {
|
|
this.webSocketService.observeControl<IDEMessage>('ide.read').pipe(first()).subscribe(
|
|
() => this.autoDetectEditorLanguage(this.filename)
|
|
);
|
|
}
|
|
|
|
reloadHandler(message: WebSocketMessage) {
|
|
if (!this.reloadFile) {
|
|
this.reloadFile = true;
|
|
this.requestCode();
|
|
}
|
|
}
|
|
|
|
readHandler(message: IDEMessage) {
|
|
if (!this.reloadFile && message.reload) {
|
|
return;
|
|
}
|
|
this.reloadFile = false;
|
|
|
|
if (this.codeState === CodeState.SAVED) {
|
|
if (this.filename !== message.filename) {
|
|
this.filename = message.filename;
|
|
}
|
|
this.code = (message.content != null) ? message.content : this.code;
|
|
this.files = message.files;
|
|
if (this.lastFilename !== this.filename) {
|
|
this.autoDetectEditorLanguage(this.filename);
|
|
}
|
|
this.lastFilename = this.filename;
|
|
}
|
|
}
|
|
|
|
writeHandler(message: IDEMessage) {
|
|
this.setCodeState(CodeState.SAVED);
|
|
}
|
|
|
|
deployHandler(message: DeployMessage) {
|
|
if ('error' in message) {
|
|
this.setDeployButtonState(DeployButtonState.FAILED);
|
|
} else {
|
|
this.setDeployButtonState(DeployButtonState.DEPLOYED);
|
|
}
|
|
this.deploymentNotificationService.deploying.next(false);
|
|
}
|
|
|
|
autoDetectEditorLanguage(filename: string) {
|
|
const extension = filename.substr(filename.lastIndexOf('.') + 1);
|
|
let language = LanguageMap[extension];
|
|
language = (language === undefined) ? 'text' : language;
|
|
this.setEditorLanguage(language);
|
|
}
|
|
|
|
setEditorLanguage(lang: string) {
|
|
this.editorOptions = Object.assign(
|
|
{},
|
|
this.editorOptions,
|
|
{ language: lang }
|
|
);
|
|
}
|
|
|
|
resetAutoSaveCountdown() {
|
|
if (this.autosave) {
|
|
clearInterval(this.autosave);
|
|
}
|
|
this.autosave = setInterval(
|
|
() => { this.sendCodeIfDirty(); },
|
|
this.configService.autoSaveInterval.value
|
|
);
|
|
}
|
|
|
|
tabSwitchButtonHandler(file: string) {
|
|
if (this.codeState === CodeState.DIRTY) {
|
|
this.sendCodeContents();
|
|
}
|
|
this.filename = file;
|
|
this.requestCode();
|
|
}
|
|
|
|
editorWriteHandler() {
|
|
this.setCodeState(CodeState.DIRTY);
|
|
this.setDeployButtonState(DeployButtonState.TODEPLOY);
|
|
this.resetAutoSaveCountdown();
|
|
}
|
|
|
|
setCodeState(state: CodeState) {
|
|
this.codeState = state;
|
|
}
|
|
|
|
setDeployButtonState(state: DeployButtonState) {
|
|
this.deployButtonState = state;
|
|
}
|
|
|
|
deployCode() {
|
|
this.webSocketService.send({'key': 'deploy.start'});
|
|
this.setDeployButtonState(DeployButtonState.DEPLOYING);
|
|
this.deploymentNotificationService.deploying.next(true);
|
|
}
|
|
|
|
sendCodeIfDirty() {
|
|
if (this.codeState === CodeState.DIRTY) {
|
|
this.sendCodeContents();
|
|
}
|
|
}
|
|
|
|
pathBasename(path: string) {
|
|
return path.split('/').reverse()[0];
|
|
}
|
|
|
|
sendCodeContents() {
|
|
this.webSocketService.send({
|
|
'key': 'ide.write',
|
|
'filename': this.filename,
|
|
'content': this.code
|
|
});
|
|
}
|
|
|
|
requestCode() {
|
|
this.webSocketService.send({
|
|
'key': 'ide.read',
|
|
'filename': this.filename,
|
|
'reload': this.reloadFile
|
|
});
|
|
}
|
|
}
|