Skip to content
Merged
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
3 changes: 3 additions & 0 deletions src/electronApp/angularApp/ directives/dragDropDirective.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export class DragDropDirective {
evt.preventDefault();
evt.stopPropagation();

// Remove CSS class from element
this.elementClass = '';

const files = evt.dataTransfer.files;
if (files.length > 0) {
// If multiple files were dropped, use only the first
Expand Down
4 changes: 3 additions & 1 deletion src/electronApp/angularApp/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { DragDropDirective } from './ directives/dragDropDirective';
import { CameraComponent } from './components/camera/camera.component';
import { ConnectionErrorDialogComponent } from './components/connection-error-dialog/connection-error-dialog.component';
import { StopPrintingConfirmationDialogComponent } from './components/stop-printing-confirmation-dialog/stop-printing-confirmation-dialog.component';
import { TransferringDialogComponent } from './components/transferring-dialog/transferring-dialog.component';

/**
* The app module.
Expand All @@ -32,7 +33,8 @@ import { StopPrintingConfirmationDialogComponent } from './components/stop-print
DragDropDirective,
CameraComponent,
ConnectionErrorDialogComponent,
StopPrintingConfirmationDialogComponent
StopPrintingConfirmationDialogComponent,
TransferringDialogComponent
],
imports: [
BrowserModule,
Expand Down
28 changes: 7 additions & 21 deletions src/electronApp/angularApp/components/print/print.component.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
<ng-container
*ngIf="SendInProgress; then sending; else ready">
</ng-container>

<ng-template #ready>
<div #ready class="uploadFileContainer" (click)="fileInput.click()" appDragDrop (FileDropped)="uploadFile($event)">
<span *ngIf="ErrorMessage" class="error warningColor">{{ErrorMessage}}</span>
<span *ngIf="Success" class="success">File transferred successfully 🙂</span>
<span class="instructions drag">To print a .gx .gcode or .g file, drag it here or click to pick.</span>
<span class="instructions drop">Drop file here to print it.</span>
<input hidden type="file" #fileInput (change)="uploadFile($event.target.files)">
</div>
</ng-template>

<ng-template #sending>
<div #sending class="sendInProgress">
<mat-spinner diameter="50"></mat-spinner>
<br>
<span>Transferring file to printer</span>
</div>
</ng-template>
<div class="uploadFileContainer" (click)="fileInput.click()" appDragDrop (FileDropped)="uploadFile($event)">
<span *ngIf="ErrorMessage" class="error warningColor">{{ErrorMessage}}</span>
<span *ngIf="Success" class="success">File transferred successfully 🙂</span>
<span class="instructions drag">To print a .gx .gcode or .g file, drag it here or click to pick.</span>
<span class="instructions drop">Drop file here to print it.</span>
<input hidden type="file" #fileInput (change)="uploadFile($event.target.files)">
</div>
74 changes: 53 additions & 21 deletions src/electronApp/angularApp/components/print/print.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { PrinterService } from '../../services/printerService';
import { ErrorLogger } from 'electronApp/core/errorLogger';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { TransferringDialogComponent } from "../transferring-dialog/transferring-dialog.component"

/**
* The Print component for sending files to the printer.
Expand All @@ -22,16 +24,21 @@ export class PrintComponent implements OnInit {
public ErrorMessage: string;

/**
* Gets a value indicating that a file transfer is in progress.
* Gets a value indicating that a file transfer was successful.
*/
public SendInProgress = false;
public Success: boolean;

/**
* Gets a value indicating that a file transfer was successful.
* Reference to the transferring dialog.
*/
public Success: boolean;
private dialogRef: MatDialogRef<TransferringDialogComponent> = null;

constructor(private printerService: PrinterService) {
/**
* Initializes a new instance of the StatusComponent class.
* @param printerService Teh printer service.
* @param dialog A material dialog.
*/
constructor(private printerService: PrinterService, private dialog: MatDialog) {

}

Expand All @@ -41,32 +48,57 @@ export class PrintComponent implements OnInit {
ngOnInit(): void {
}

/**
* Invoked when the Angular component is destroyed.
*/
ngOnDestroy(): void {
if (this.dialogRef) {
this.dialogRef.close();
}
}

/**
* Sends a selected file to the printer/
* @param event The HTML event args.
*/
public async uploadFile(event): Promise<void> {
public uploadFile(event): void {
const path = event[0].path;

if (path){
try{
this.SendInProgress = true;
this.Success = false;
this.ErrorMessage = null;
const startTime = new Date().getTime();

ErrorLogger.Trace("PrintComponent::uploadFile - Storing file");
await this.printerService.StoreFileAsync(path)
// Show a dialog
this.dialogRef = this.dialog.open(TransferringDialogComponent);
this.dialogRef.disableClose = true;

ErrorLogger.Trace("PrintComponent::uploadFile - Printing file");
await this.printerService.PrintFileAsync(event[0].name);
this.Success = true;
}
catch(e){
ErrorLogger.NonFatalError(e);
this.ErrorMessage = 'Failed to send file to printer.';
}
setImmediate(async () => {
try{
this.Success = false;
this.ErrorMessage = null;

ErrorLogger.Trace("PrintComponent::uploadFile - Storing file");
await this.printerService.StoreFileAsync(path)

ErrorLogger.Trace("PrintComponent::uploadFile - Printing file");
await this.printerService.PrintFileAsync(event[0].name);
this.Success = true;
}
catch(e){
ErrorLogger.NonFatalError(e);
this.ErrorMessage = 'Failed to send file to printer.';
}

// Introduce a small delay so that with small files
// the user gets to actually see the UI rather than a flicker
const endTime = new Date().getTime();
const duration = endTime - startTime;
const delay = Math.max(0, 800 - duration);

this.SendInProgress = false;
setTimeout(() => {
this.dialogRef.close();
this.dialogRef = null;
}, delay);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="StopPrintingConfirmationContainer">
<h1 mat-dialog-title>Stop Printing</h1>

<div mat-dialog-content>Are you sure you want to stop printing.</div>
<div mat-dialog-content>Are you sure you want to stop printing?</div>

<mat-dialog-actions align="end">
<button (click)="Cancel()" mat-button mat-dialog-close>Cancel</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.sendInProgress {
display: flex;
align-items: center;
flex-direction: column;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div #sending class="sendInProgress">
<mat-spinner diameter="50"></mat-spinner>
<br>
<span>Please wait. Transferring file to printer.</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, OnInit, Inject, ChangeDetectorRef, ApplicationRef, ViewChild, ElementRef } from '@angular/core';

@Component({
selector: 'app-transferring-dialog',
templateUrl: './transferring-dialog.component.html',
styleUrls: ['./transferring-dialog.component.css']
})
export class TransferringDialogComponent implements OnInit {

/**
* Invoked when the Angular component is initialized.
*/
ngOnInit(): void {
}

}
3 changes: 3 additions & 0 deletions src/electronApp/angularApp/material/material.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatTableModule} from '@angular/material/table';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatDialogModule} from '@angular/material/dialog';
import {MatProgressBarModule} from '@angular/material/progress-bar';

/**
* Modulus containing the requires Angular material modules.
Expand All @@ -26,6 +27,7 @@ import {MatDialogModule} from '@angular/material/dialog';
MatFormFieldModule,
MatInputModule,
MatProgressSpinnerModule,
MatProgressBarModule,
MatTableModule,
MatCheckboxModule,
MatDialogModule
Expand All @@ -38,6 +40,7 @@ import {MatDialogModule} from '@angular/material/dialog';
MatFormFieldModule,
MatInputModule,
MatProgressSpinnerModule,
MatProgressBarModule,
MatTableModule,
MatCheckboxModule,
MatDialogModule
Expand Down
4 changes: 2 additions & 2 deletions src/electronApp/angularApp/services/iPrinterService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PrinterStatus, FirmwareVersionResponse, TemperatureResponse, PrinterDebugMonitor } from '../../printerSdk/entities';
import { PrinterCamera } from '../../printerSdk/printerCamera'
import { EventDispatcher } from '../../core/eventDispatcher';
import { EventDispatcher, PromiseWithProgress } from '../../core';

/**
* Interface fot the printer service.
Expand Down Expand Up @@ -77,7 +77,7 @@ export interface IPrinterService {
* will be renamed to .g.
* @param filePath The path of the file to transferer.
*/
StoreFileAsync(filePath: string): Promise<void>;
StoreFileAsync(filePath: string): PromiseWithProgress<void>;

/**
* Requests the firmware version info from the printer.
Expand Down
7 changes: 3 additions & 4 deletions src/electronApp/angularApp/services/printerService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Injectable } from '@angular/core';
import { IPrinterService } from './iPrinterService';
import { PrinterStatus, TemperatureResponse, FirmwareVersionResponse, PrinterDebugMonitor } from '../../printerSdk/entities';
import { EventDispatcher } from '../../core/eventDispatcher';
import { PrinterStatus, TemperatureResponse, FirmwareVersionResponse, PrinterDebugMonitor, } from '../../printerSdk/entities';
import { Printer } from '../../printerSdk/printer';
import { ErrorLogger } from '../../core/errorLogger';
import { PrinterCamera } from '../../printerSdk/printerCamera'
import { ErrorLogger, PromiseWithProgress, EventDispatcher } from '../../core';

const path = window.require('path');

Expand Down Expand Up @@ -154,7 +153,7 @@ export class PrinterService implements IPrinterService {
}

/** @inheritdoc */
public StoreFileAsync(filePath: string): Promise<void> {
public StoreFileAsync(filePath: string): PromiseWithProgress<void>{
if (this.printer == null) {
throw new Error('Cannot call this method before calling and awaiting ConnectAsnc()');
}
Expand Down
36 changes: 36 additions & 0 deletions src/electronApp/core/PromiseWithProgress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { EventDispatcher } from './eventDispatcher';

/**
* A wrapper around a promise, which also provides a progress update.
*/
export class PromiseWithProgress<T> {
/**
* The promise to the completion of the operation.
*/
public readonly Promise: Promise<T>;

/**
* Event raised when there is an update to the progress.
*/
public readonly Progress = new EventDispatcher<number>();

/**
* Initializes a new instance of the StatusComponent class.
* @param func The function to execute.
*/
constructor (func: (updateProgress: (value: number) => void) => Promise<T>){
this.Promise = func((value: number) => this.UpdateProgress(value));
}

/**
* Updates the current progress.
* @param value
*/
private UpdateProgress(value: number): void{
if (value < 0 || value > 1){
throw new Error("Value is out of range");
}

this.Progress.Invoke(value);
}
}
3 changes: 3 additions & 0 deletions src/electronApp/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './errorLogger';
export * from './eventDispatcher';
export * from './PromiseWithProgress';
19 changes: 18 additions & 1 deletion src/electronApp/printerSdk/printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PrinterResponseReader } from './printerResponseReader';
import { PrinterCamera } from './printerCamera'
import { PrinterStatus, FirmwareVersionResponse, TemperatureResponse, IPrinterResponse, PrinterDebugMonitor } from './entities';
import { MachineCommands } from './machineCommands';
import { PromiseWithProgress } from '../core/PromiseWithProgress'

/**
* Represents the printer.
Expand Down Expand Up @@ -225,12 +226,24 @@ export class Printer {
return this.WaitForPrinterAck(MachineCommands.PrintFileFromSd);
}

/**
* Transfers a file to the printer's storage with a given name.
* @param filePath The path to the file to transfer.
* @param fileName The name of the file to store it as (without file extension)
*/
StoreFileAsync(filePath: string, fileName: string): PromiseWithProgress<void> {
return new PromiseWithProgress<void>((updateProgress: (value: number) => void) => {
return this.StoreFileAsyncInternal(filePath, fileName, updateProgress);
});
}

/**
* Transfers a file to the printer's storage with a given name.
* @param filePath The path to the file to transfer.
* @param fileName The name of the file to store it as (without file extension)
* @param updateProgress The function to cal with progress updates
*/
async StoreFileAsync(filePath: string, fileName: string): Promise<void> {
private async StoreFileAsyncInternal(filePath: string, fileName: string, updateProgress: (number: number) => void): Promise<void> {
this.ValidatePrinterReady();

// Load the file from disk
Expand Down Expand Up @@ -303,6 +316,10 @@ export class Printer {
// Send it to the printer
this.SendBufferToPrinter(bufferToSend);

// Update the progress
const progress = offset / modelBytes.length;
updateProgress(progress);

offset += this.packetSizeBytes;
++count;
}
Expand Down