mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 20:47:54 +00:00
improve socket
This commit is contained in:
@@ -40,19 +40,23 @@
|
|||||||
|
|
||||||
|
|
||||||
<ion-img *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'image'" [(ngModel)]="capturedImage"
|
<ion-img *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'image'" [(ngModel)]="capturedImage"
|
||||||
name="image" ngDefaultControl [src]="'data:image/jpg;base64,' + seleted.FileBase64"
|
name="image" ngDefaultControl [src]="'data:image/jpg;base64,' + seleted.Base64"
|
||||||
(click)="imageSize(capturedImage)" style="height: 69px;"></ion-img>
|
(click)="imageSize(capturedImage)" style="height: 69px;"></ion-img>
|
||||||
|
|
||||||
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video'" width="70" height="70"
|
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && publicationTitle == ActionType.edit" width="70" height="70"
|
||||||
controls="controls" preload="metadata" autoplay="autoplay" webkit-playsinline="webkit-playsinline">
|
controls="controls" preload="metadata" autoplay="autoplay" webkit-playsinline="webkit-playsinline">
|
||||||
<source type="video/mp4" [src]="'data:video/mp4;base64,' + seleted.FileBase64">
|
<source type="video/mp4" [src]="'data:video/mp4;base64,' + seleted.Base64">
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
|
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && publicationTitle != ActionType.edit" width="70" height="70"
|
||||||
|
controls="controls" preload="metadata" autoplay="autoplay" webkit-playsinline="webkit-playsinline">
|
||||||
|
<source type="video/mp4" [src]="seleted.url">
|
||||||
|
</video>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Display the blurred image and count if there are more images -->
|
<!-- Display the blurred image and count if there are more images -->
|
||||||
<ion-thumbnail *ngIf="seletedContent.length > displayLimit" lot="start">
|
<ion-thumbnail *ngIf="seletedContent.length > displayLimit" lot="start">
|
||||||
<ion-img [src]="'data:image/jpg;base64,' + seletedContent[displayLimit - 1].base64"
|
<ion-img [src]="'data:image/jpg;base64,' + seletedContent[displayLimit - 1].Base64"
|
||||||
style="filter: blur(5px);"></ion-img>
|
style="filter: blur(5px);"></ion-img>
|
||||||
|
|
||||||
<p>mais {{ seletedContent.length - displayLimit }}</p>
|
<p>mais {{ seletedContent.length - displayLimit }}</p>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { File } from '@ionic-native/file/ngx';
|
|||||||
import { Media } from '@ionic-native/media/ngx';
|
import { Media } from '@ionic-native/media/ngx';
|
||||||
import { checkFileTypeService } from 'src/app/services/checkFileType.service';
|
import { checkFileTypeService } from 'src/app/services/checkFileType.service';
|
||||||
import { FileValidatorService } from "src/app/services/file/file-validator.service"
|
import { FileValidatorService } from "src/app/services/file/file-validator.service"
|
||||||
|
import { PublicationAttachmentEntity } from 'src/app/shared/publication/upload/upload-streaming.service';
|
||||||
const config = {
|
const config = {
|
||||||
quality: 0.5,
|
quality: 0.5,
|
||||||
maxWidth: 800,
|
maxWidth: 800,
|
||||||
@@ -92,6 +93,13 @@ export class NewPublicationPage implements OnInit {
|
|||||||
publicationTitle: string;
|
publicationTitle: string;
|
||||||
imgUrl: any;
|
imgUrl: any;
|
||||||
|
|
||||||
|
|
||||||
|
ActionType = {
|
||||||
|
newRapid : "1",
|
||||||
|
new: "2",
|
||||||
|
edit: "3"
|
||||||
|
}
|
||||||
|
|
||||||
Defaultimage: any = '';
|
Defaultimage: any = '';
|
||||||
|
|
||||||
photo: SafeResourceUrl;
|
photo: SafeResourceUrl;
|
||||||
@@ -112,7 +120,7 @@ export class NewPublicationPage implements OnInit {
|
|||||||
photoOrVideo: boolean = false;
|
photoOrVideo: boolean = false;
|
||||||
fileType = "";
|
fileType = "";
|
||||||
filecontent: boolean;
|
filecontent: boolean;
|
||||||
seletedContent: any[] = []
|
seletedContent: PublicationAttachmentEntity[] = []
|
||||||
// Set a limit for the number of images to display
|
// Set a limit for the number of images to display
|
||||||
displayLimit = 4;
|
displayLimit = 4;
|
||||||
filesSizeSum = 0;
|
filesSizeSum = 0;
|
||||||
@@ -142,6 +150,18 @@ export class NewPublicationPage implements OnInit {
|
|||||||
if (this.publication) {
|
if (this.publication) {
|
||||||
this.seletedContent = this.publication.Files;
|
this.seletedContent = this.publication.Files;
|
||||||
this.filecontent = true;
|
this.filecontent = true;
|
||||||
|
|
||||||
|
this.seletedContent = this.publication.Files.map(e => {
|
||||||
|
return new PublicationAttachmentEntity(
|
||||||
|
{
|
||||||
|
base64: e.FileBase64,
|
||||||
|
extension: e.FileExtension,
|
||||||
|
OriginalFileName: e.OriginalFileName,
|
||||||
|
FileType: this.checkFileType.checkFileType(e.FileExtension) as any
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
console.log('Edit', this.publication)
|
console.log('Edit', this.publication)
|
||||||
this.publicationTitle = 'Nova Publicação';
|
this.publicationTitle = 'Nova Publicação';
|
||||||
@@ -161,12 +181,16 @@ export class NewPublicationPage implements OnInit {
|
|||||||
recursive: true
|
recursive: true
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("click", clickOutside, false);
|
try {
|
||||||
function clickOutside(e) {
|
document.addEventListener("click", clickOutside, false);
|
||||||
const inside = document.getElementById('container-multiselect').contains(e.target);
|
function clickOutside(e) {
|
||||||
this.photoOrVideo = false;
|
const inside = document.getElementById('container-multiselect').contains(e.target);
|
||||||
console.log(this.photoOrVideo)
|
this.photoOrVideo = false;
|
||||||
}
|
console.log(this.photoOrVideo)
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// in use
|
// in use
|
||||||
@@ -193,11 +217,14 @@ export class NewPublicationPage implements OnInit {
|
|||||||
console.log('take picture', this.removeTextBeforeSlash(picture, ','),)
|
console.log('take picture', this.removeTextBeforeSlash(picture, ','),)
|
||||||
this.filecontent = true;
|
this.filecontent = true;
|
||||||
this.photoOrVideo = false;
|
this.photoOrVideo = false;
|
||||||
let fileObject = {
|
|
||||||
FileBase64: this.removeTextBeforeSlash(picture, ','),
|
const fileObject = new PublicationAttachmentEntity({
|
||||||
FileExtension: capturedImage.format,
|
base64: this.removeTextBeforeSlash(picture, ','),
|
||||||
|
extension: capturedImage.format,
|
||||||
|
FileType: 'image',
|
||||||
OriginalFileName: 'image'
|
OriginalFileName: 'image'
|
||||||
}
|
})
|
||||||
|
|
||||||
this.seletedContent.push(fileObject)
|
this.seletedContent.push(fileObject)
|
||||||
|
|
||||||
|
|
||||||
@@ -251,11 +278,14 @@ export class NewPublicationPage implements OnInit {
|
|||||||
|
|
||||||
.then(async (content) => {
|
.then(async (content) => {
|
||||||
this.filecontent = true;
|
this.filecontent = true;
|
||||||
let fileObject = {
|
let fileObject = new PublicationAttachmentEntity({
|
||||||
FileBase64: 'data:video/mp4;base64,'+content.data,
|
base64: 'data:video/mp4;base64,'+content.data,
|
||||||
FileExtension: 'mp4',
|
extension: 'mp4',
|
||||||
OriginalFileName: 'video'
|
OriginalFileName: 'record',
|
||||||
}
|
FileType: 'video'
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
this.seletedContent.push(fileObject)
|
this.seletedContent.push(fileObject)
|
||||||
})
|
})
|
||||||
.catch((err) => console.error(err));
|
.catch((err) => console.error(err));
|
||||||
@@ -294,17 +324,28 @@ export class NewPublicationPage implements OnInit {
|
|||||||
this.filecontent = true;
|
this.filecontent = true;
|
||||||
let fileObject;
|
let fileObject;
|
||||||
if(this.removeTextBeforeSlash(element.mimeType, '/') == "mp4") {
|
if(this.removeTextBeforeSlash(element.mimeType, '/') == "mp4") {
|
||||||
fileObject = {
|
|
||||||
FileBase64: 'data:video/mp4;base64,'+ content.data,
|
const extension = this.removeTextBeforeSlash(element.mimeType, '/')
|
||||||
FileExtension: this.removeTextBeforeSlash(element.mimeType, '/'),
|
|
||||||
OriginalFileName: 'video'
|
fileObject = new PublicationAttachmentEntity({
|
||||||
}
|
base64: content.data,
|
||||||
|
extension: extension,
|
||||||
|
OriginalFileName: 'video',
|
||||||
|
FileType: 'video'
|
||||||
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fileObject = {
|
|
||||||
FileBase64: content.data,
|
const extension = this.removeTextBeforeSlash(element.mimeType, '/')
|
||||||
FileExtension: this.removeTextBeforeSlash(element.mimeType, '/'),
|
|
||||||
OriginalFileName: 'image'
|
fileObject = new PublicationAttachmentEntity({
|
||||||
}
|
base64: content.data,
|
||||||
|
extension: extension,
|
||||||
|
OriginalFileName: 'image',
|
||||||
|
FileType: 'image'
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.seletedContent.push(fileObject)
|
this.seletedContent.push(fileObject)
|
||||||
@@ -533,8 +574,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await this.publications.CreatePublication(this.folderId, this.publication).toPromise();
|
await this.publications.CreatePublication(this.folderId, this.publication).toPromise();
|
||||||
this.close();
|
this.close();
|
||||||
this.httpErrorHandle.httpsSucessMessagge('Criar publicação')
|
this.httpErrorHandle.httpsSucessMessagge('Criar publicação')
|
||||||
@@ -740,12 +779,16 @@ export class NewPublicationPage implements OnInit {
|
|||||||
if (this.checkFileType.checkFileType(FileExtension) == 'image' || this.checkFileType.checkFileType(FileExtension) == 'video') {
|
if (this.checkFileType.checkFileType(FileExtension) == 'image' || this.checkFileType.checkFileType(FileExtension) == 'video') {
|
||||||
let resultUrl = decodeURIComponent(element.url);
|
let resultUrl = decodeURIComponent(element.url);
|
||||||
Filesystem.readFile({ path: resultUrl }).then(async (content) => {
|
Filesystem.readFile({ path: resultUrl }).then(async (content) => {
|
||||||
console.log('shared base', content.data)
|
|
||||||
let fileObject = {
|
let fileObject = new PublicationAttachmentEntity(
|
||||||
FileBase64: this.removeTextBeforeSlash(content.data, ','),
|
{
|
||||||
FileExtension: FileExtension,
|
base64: this.removeTextBeforeSlash(content.data, ','),
|
||||||
OriginalFileName: 'shared',
|
extension: FileExtension,
|
||||||
}
|
OriginalFileName: "share-content",
|
||||||
|
FileType: this.checkFileType.checkFileType(FileExtension) as any
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
this.seletedContent.push(fileObject)
|
this.seletedContent.push(fileObject)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export class PublicationsPage implements OnInit {
|
|||||||
|
|
||||||
this.hideRefreshButton();
|
this.hideRefreshButton();
|
||||||
this.intent = window["sharedContent"]
|
this.intent = window["sharedContent"]
|
||||||
|
window["refreshPublication"] = this.refreshing
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +125,7 @@ export class PublicationsPage implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshing() {
|
refreshing = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.getActions();
|
this.getActions();
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|||||||
@@ -10,60 +10,60 @@ import { HubConnectionBuilder } from '@microsoft/signalr';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class SocketConnectionMCRService {
|
export class SocketConnectionMCRService {
|
||||||
private callbacks: Function[] = []
|
// private callbacks: Function[] = []
|
||||||
private onDisconnect: Function[] = []
|
// private onDisconnect: Function[] = []
|
||||||
private onConnect: Function[] = []
|
// private onConnect: Function[] = []
|
||||||
|
|
||||||
constructor(private http: HttpClient,) {
|
// constructor(private http: HttpClient,) {
|
||||||
window["http"] = this.http
|
// window["http"] = this.http
|
||||||
}
|
// }
|
||||||
|
|
||||||
connect() {
|
// connect() {
|
||||||
|
|
||||||
var connection = new signalR.HubConnectionBuilder()
|
// var connection = new signalR.HubConnectionBuilder()
|
||||||
.withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
|
// .withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
|
||||||
accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
|
// accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
|
||||||
}).configureLogging(signalR.LogLevel.Information)
|
// }).configureLogging(signalR.LogLevel.Information)
|
||||||
.build();
|
// .build();
|
||||||
|
|
||||||
connection.on("ReceiveMessage", (message) => {
|
// connection.on("ReceiveMessage", (message) => {
|
||||||
console.log("ReceiveMessage", message)
|
// console.log("ReceiveMessage", message)
|
||||||
})
|
// })
|
||||||
|
|
||||||
connection.onreconnected((connectionId) => {
|
// connection.onreconnected((connectionId) => {
|
||||||
console.assert(connection.state === signalR.HubConnectionState.Connected);
|
// console.assert(connection.state === signalR.HubConnectionState.Connected);
|
||||||
console.log(`Reconnected with connectionId: ${connectionId}`);
|
// console.log(`Reconnected with connectionId: ${connectionId}`);
|
||||||
});
|
// });
|
||||||
|
|
||||||
connection.start()
|
// connection.start()
|
||||||
.then(() => {
|
// .then(() => {
|
||||||
console.log("SignalR connection started.");
|
// console.log("SignalR connection started.");
|
||||||
})
|
// })
|
||||||
.catch((error) => {
|
// .catch((error) => {
|
||||||
console.error("Error starting SignalR connection:", error);
|
// console.error("Error starting SignalR connection:", error);
|
||||||
});
|
// });
|
||||||
|
|
||||||
connection.onclose((error) => {
|
// connection.onclose((error) => {
|
||||||
connection.start()
|
// connection.start()
|
||||||
console.log("SignalR connection closed:", error);
|
// console.log("SignalR connection closed:", error);
|
||||||
});
|
// });
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
subscribe(callback) {
|
// subscribe(callback) {
|
||||||
this.callbacks.push(callback);
|
// this.callbacks.push(callback);
|
||||||
}
|
// }
|
||||||
|
|
||||||
unsubscribe(callback) {
|
// unsubscribe(callback) {
|
||||||
this.callbacks = this.callbacks.filter(cb => cb !== callback);
|
// this.callbacks = this.callbacks.filter(cb => cb !== callback);
|
||||||
}
|
// }
|
||||||
|
|
||||||
onDisconnectCallback(callback) {
|
// onDisconnectCallback(callback) {
|
||||||
this.onDisconnect.push(callback)
|
// this.onDisconnect.push(callback)
|
||||||
}
|
// }
|
||||||
onConnectCallback(callback) {
|
// onConnectCallback(callback) {
|
||||||
this.onConnect.push(callback)
|
// this.onConnect.push(callback)
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +74,7 @@ class ReconnectingWebSocketSignalR {
|
|||||||
private callbacks: Function[] = []
|
private callbacks: Function[] = []
|
||||||
private onDisconnect: Function[] = []
|
private onDisconnect: Function[] = []
|
||||||
private onConnect: Function[] = []
|
private onConnect: Function[] = []
|
||||||
|
private stop = true
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
@@ -81,9 +82,13 @@ class ReconnectingWebSocketSignalR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
|
console.log("try to connect=================================")
|
||||||
|
this.stop = false
|
||||||
|
|
||||||
this.connection = new signalR.HubConnectionBuilder()
|
this.connection = new signalR.HubConnectionBuilder()
|
||||||
.withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
|
.withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
|
||||||
accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
|
transport: signalR.HttpTransportType.LongPolling,
|
||||||
|
accessTokenFactory: () => SessionStore.user.Authorization
|
||||||
}).configureLogging(signalR.LogLevel.Information)
|
}).configureLogging(signalR.LogLevel.Information)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -95,16 +100,15 @@ class ReconnectingWebSocketSignalR {
|
|||||||
|
|
||||||
|
|
||||||
this.onConnect.forEach(callback => callback());
|
this.onConnect.forEach(callback => callback());
|
||||||
console.log("SignalR connection started.");
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Error starting SignalR connection:", error);
|
console.error("Error starting SignalR connection:", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.connection.on("ReceiveMessage", (message) => {
|
this.connection.on("ReceiveMessage", (message) => {
|
||||||
const data: any = JSON.parse(message)
|
const data: any = JSON.parse(message)
|
||||||
console.log(data)
|
console.log("ReceiveMessage", data)
|
||||||
this.callbacks.forEach(callback => callback(data));
|
this.callbacks.forEach(callback => callback(data));
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -113,12 +117,27 @@ class ReconnectingWebSocketSignalR {
|
|||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
this.onDisconnect.forEach(callback => callback());
|
this.onDisconnect.forEach(callback => callback());
|
||||||
// Attempt to reconnect after a delay
|
// Attempt to reconnect after a delay
|
||||||
setTimeout(() => {
|
if(this.stop) {
|
||||||
this.connect();
|
setTimeout(() => {
|
||||||
}, 1000); // Adjust the delay as needed
|
this.connect();
|
||||||
|
}, 1000); // Adjust the delay as needed
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.stop = true
|
||||||
|
this.connection.stop()
|
||||||
|
.then(() => {
|
||||||
|
console.log('WebSocket connection closed');
|
||||||
|
this.isOpen = false;
|
||||||
|
this.onDisconnect.forEach(callback => callback());
|
||||||
|
console.log("SignalR connection stopped.");
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error stopping SignalR connection:", error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(callback) {
|
subscribe(callback) {
|
||||||
@@ -143,81 +162,81 @@ interface socketResponse {
|
|||||||
Guid: string
|
Guid: string
|
||||||
isCompleted: Boolean
|
isCompleted: Boolean
|
||||||
}
|
}
|
||||||
class ReconnectingWebSocket {
|
// class ReconnectingWebSocket {
|
||||||
|
|
||||||
private url: string
|
// private url: string
|
||||||
private socket
|
// private socket
|
||||||
isOpen: boolean
|
// isOpen: boolean
|
||||||
private callbacks: Function[] = []
|
// private callbacks: Function[] = []
|
||||||
private onDisconnect: Function[] = []
|
// private onDisconnect: Function[] = []
|
||||||
private onConnect: Function[] = []
|
// private onConnect: Function[] = []
|
||||||
|
|
||||||
http: HttpClient = window["http"]
|
// http: HttpClient = window["http"]
|
||||||
|
|
||||||
constructor(url) {
|
// constructor(url) {
|
||||||
this.url = url;
|
// this.url = url;
|
||||||
this.socket = null;
|
// this.socket = null;
|
||||||
this.isOpen = false;
|
// this.isOpen = false;
|
||||||
this.connect();
|
// this.connect();
|
||||||
}
|
// }
|
||||||
|
|
||||||
connect() {
|
// connect() {
|
||||||
this.socket = new WebSocket(this.url);
|
// this.socket = new WebSocket(this.url);
|
||||||
|
|
||||||
this.socket.addEventListener('open', (event) => {
|
// this.socket.addEventListener('open', (event) => {
|
||||||
this.isOpen = true;
|
// this.isOpen = true;
|
||||||
console.log('WebSocket connection established');
|
// console.log('WebSocket connection established');
|
||||||
|
|
||||||
// Example: Send a message to the server
|
// // Example: Send a message to the server
|
||||||
this.socket.send('Hello, WebSocket Server!');
|
// this.socket.send('Hello, WebSocket Server!');
|
||||||
this.onConnect.forEach(callback => callback());
|
// this.onConnect.forEach(callback => callback());
|
||||||
});
|
// });
|
||||||
|
|
||||||
this.socket.addEventListener('message', (event) => {
|
// this.socket.addEventListener('message', (event) => {
|
||||||
const data: socketResponse = JSON.parse(event.data)
|
// const data: socketResponse = JSON.parse(event.data)
|
||||||
this.callbacks.forEach(callback => callback(data));
|
// this.callbacks.forEach(callback => callback(data));
|
||||||
});
|
// });
|
||||||
|
|
||||||
this.socket.addEventListener('close', (event) => {
|
// this.socket.addEventListener('close', (event) => {
|
||||||
console.log('WebSocket connection closed');
|
// console.log('WebSocket connection closed');
|
||||||
this.isOpen = false;
|
// this.isOpen = false;
|
||||||
this.onDisconnect.forEach(callback => callback());
|
// this.onDisconnect.forEach(callback => callback());
|
||||||
// Attempt to reconnect after a delay
|
// // Attempt to reconnect after a delay
|
||||||
setTimeout(() => {
|
// setTimeout(() => {
|
||||||
this.connect();
|
// this.connect();
|
||||||
}, 1000); // Adjust the delay as needed
|
// }, 1000); // Adjust the delay as needed
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
send(message) {
|
// send(message) {
|
||||||
if (this.isOpen) {
|
// if (this.isOpen) {
|
||||||
this.socket.send(message);
|
// this.socket.send(message);
|
||||||
} else {
|
// } else {
|
||||||
console.error('WebSocket connection is not open. Unable to send message.');
|
// console.error('WebSocket connection is not open. Unable to send message.');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
close() {
|
// close() {
|
||||||
if (this.isOpen) {
|
// if (this.isOpen) {
|
||||||
this.socket.close();
|
// this.socket.close();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
subscribe(callback) {
|
// subscribe(callback) {
|
||||||
this.callbacks.push(callback);
|
// this.callbacks.push(callback);
|
||||||
}
|
// }
|
||||||
|
|
||||||
unsubscribe(callback) {
|
// unsubscribe(callback) {
|
||||||
this.callbacks = this.callbacks.filter(cb => cb !== callback);
|
// this.callbacks = this.callbacks.filter(cb => cb !== callback);
|
||||||
}
|
// }
|
||||||
|
|
||||||
onDisconnectCallback(callback) {
|
// onDisconnectCallback(callback) {
|
||||||
this.onDisconnect.push(callback)
|
// this.onDisconnect.push(callback)
|
||||||
}
|
// }
|
||||||
onConnectCallback(callback) {
|
// onConnectCallback(callback) {
|
||||||
this.onConnect.push(callback)
|
// this.onConnect.push(callback)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// export class ObjectMergeNotification{
|
// export class ObjectMergeNotification{
|
||||||
|
|
||||||
@@ -294,8 +313,10 @@ export class ObjectMergeNotification{
|
|||||||
this.runWatch = false
|
this.runWatch = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
this.socket.subscribe((data: socketResponse) => {
|
this.socket.subscribe((data: socketResponse) => {
|
||||||
if(data.isCompleted == true) {
|
if(data.isCompleted == true) {
|
||||||
|
console.log("==================!!!====================")
|
||||||
this.callbacks[data.Guid](data)
|
this.callbacks[data.Guid](data)
|
||||||
delete this.callbacks[data.Guid]
|
delete this.callbacks[data.Guid]
|
||||||
}
|
}
|
||||||
@@ -305,36 +326,9 @@ export class ObjectMergeNotification{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
connect() {
|
close() {
|
||||||
|
console.log("close=============================================")
|
||||||
var connection = new signalR.HubConnectionBuilder()
|
this.socket.disconnect();
|
||||||
.withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
|
|
||||||
accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
|
|
||||||
}).configureLogging(signalR.LogLevel.Information)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
connection.on("ReceiveMessage", (message) => {
|
|
||||||
console.log("ReceiveMessage", message)
|
|
||||||
})
|
|
||||||
|
|
||||||
connection.onreconnected((connectionId) => {
|
|
||||||
console.assert(connection.state === signalR.HubConnectionState.Connected);
|
|
||||||
console.log(`Reconnected with connectionId: ${connectionId}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.start()
|
|
||||||
.then(() => {
|
|
||||||
console.log("SignalR connection started.");
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error starting SignalR connection:", error);
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.onclose((error) => {
|
|
||||||
connection.start()
|
|
||||||
console.log("SignalR connection closed:", error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async watch() {
|
async watch() {
|
||||||
@@ -354,6 +348,8 @@ export class ObjectMergeNotification{
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log("end loop============================")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class CMAPIAPIService {
|
|||||||
|
|
||||||
|
|
||||||
getVideoHeader(url: string) {
|
getVideoHeader(url: string) {
|
||||||
// return this.http.head('http://localhost:3001/static/'+url, { observe: 'response' })
|
//return this.http.head('http://localhost:3001/static/'+url, { observe: 'response' })
|
||||||
return this.http.head(environment.apiURL+'ObjectServer/StreamFiles?path='+url, { observe: 'response' })
|
return this.http.head(environment.apiURL+'ObjectServer/StreamFiles?path='+url, { observe: 'response' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,34 +56,24 @@
|
|||||||
<ion-img *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'image'"
|
<ion-img *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'image'"
|
||||||
name="image" ngDefaultControl [src]="seleted.FileBase64" style="height: 69px;"></ion-img>
|
name="image" ngDefaultControl [src]="seleted.FileBase64" style="height: 69px;"></ion-img>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <div class="progress-container" *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video'">
|
|
||||||
<div class="progress-bar" id="myProgressBar"></div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && seleted.chucksManager">
|
<div *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && seleted.chucksManager">
|
||||||
|
|
||||||
|
|
||||||
<mat-progress-bar
|
<mat-progress-bar
|
||||||
|
|
||||||
mode="determinate"
|
mode="determinate"
|
||||||
[style.width]="seleted.chucksManager.uploadPercentage"
|
[style.width]="seleted.chucksManager.uploadPercentage"
|
||||||
></mat-progress-bar>
|
></mat-progress-bar>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && checkDesktop() == true" width="70" height="70"
|
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && checkDesktop() == true" width="70" height="70"
|
||||||
preload="metadata" webkit-playsinline="webkit-playsinline">
|
preload="metadata" webkit-playsinline="webkit-playsinline">
|
||||||
<source type="video/mp4" [src]="seleted.FileBase64">
|
<source type="video/mp4" [src]="seleted.url">
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && checkTableDivice() == true" width="70" height="70"
|
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && checkTableDivice() == true" width="70" height="70"
|
||||||
preload="metadata" webkit-playsinline="webkit-playsinline">
|
preload="metadata" webkit-playsinline="webkit-playsinline">
|
||||||
<source type="video/mp4" [src]="'data:video/mp4;base64,' +seleted.FileBase64">
|
<source type="video/mp4" [src]="'data:video/mp4;base64,' +seleted.Base64">
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
<ion-icon *ngIf="seleted?.chucksManager?.manualRetry" src="assets/images/retry-svgrepo-com.svg" class="icon-download font-12"> </ion-icon>
|
<ion-icon *ngIf="seleted?.chucksManager?.manualRetry" src="assets/images/retry-svgrepo-com.svg" class="icon-download font-12"> </ion-icon>
|
||||||
@@ -93,7 +83,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Display the blurred image and count if there are more images -->
|
<!-- Display the blurred image and count if there are more images -->
|
||||||
<div *ngIf="seletedContent.length > displayLimit" lot="start">
|
<div *ngIf="seletedContent.length > displayLimit" lot="start">
|
||||||
<ion-img [src]="'data:image/jpg;base64,' + seletedContent[displayLimit - 1].FileBase64"
|
<ion-img [src]="'data:image/jpg;base64,' + seletedContent[displayLimit - 1].Base64"
|
||||||
style="filter: blur(5px);"></ion-img>
|
style="filter: blur(5px);"></ion-img>
|
||||||
|
|
||||||
<p>mais {{ seletedContent.length - displayLimit }}</p>
|
<p>mais {{ seletedContent.length - displayLimit }}</p>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { CaptureError, CaptureImageOptions, MediaCapture, MediaFile } from '@awe
|
|||||||
import { Filesystem, Directory, Encoding, FilesystemDirectory } from '@capacitor/filesystem';
|
import { Filesystem, Directory, Encoding, FilesystemDirectory } from '@capacitor/filesystem';
|
||||||
import { Platform } from '@ionic/angular';
|
import { Platform } from '@ionic/angular';
|
||||||
import { Capacitor } from '@capacitor/core';
|
import { Capacitor } from '@capacitor/core';
|
||||||
|
import { PublicationAttachmentEntity, PublicationFormMV } from '../upload/upload-streaming.service';
|
||||||
|
|
||||||
|
|
||||||
enum ActionType {
|
enum ActionType {
|
||||||
@@ -70,9 +71,9 @@ export class NewPublicationPage implements OnInit {
|
|||||||
photoOrVideo: boolean = false;
|
photoOrVideo: boolean = false;
|
||||||
video: any;
|
video: any;
|
||||||
|
|
||||||
|
|
||||||
publicationFormMV = new PublicationFormMV()
|
publicationFormMV = new PublicationFormMV()
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public photoService: PhotoService,
|
public photoService: PhotoService,
|
||||||
private publications: PublicationsService,
|
private publications: PublicationsService,
|
||||||
@@ -97,7 +98,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
this.filecontent = true;
|
this.filecontent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.SocketConnectionMCRService.connect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -148,13 +148,15 @@ export class NewPublicationPage implements OnInit {
|
|||||||
}
|
}
|
||||||
console.log('edit', this.publication)
|
console.log('edit', this.publication)
|
||||||
this.pub = this.publication;
|
this.pub = this.publication;
|
||||||
|
|
||||||
|
console.log("this.publication.Files", this.publication.Files)
|
||||||
this.seletedContent = this.publication.Files.map(e => {
|
this.seletedContent = this.publication.Files.map(e => {
|
||||||
return new PublicationAttachmentEntity(
|
return new PublicationAttachmentEntity(
|
||||||
{
|
{
|
||||||
base64: e.FileBase64,
|
base64: e.FileBase64,
|
||||||
extension: e.FileExtension,
|
extension: e.FileExtension,
|
||||||
OriginalFileName: e.OriginalFileName,
|
OriginalFileName: e.OriginalFileName,
|
||||||
FileType: this.checkFileType.checkFileType(e.FileExtension)
|
FileType: this.checkFileType.checkFileType(e.FileExtension) as any
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -186,11 +188,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
0.9 // quality
|
0.9 // quality
|
||||||
).then((picture) => {
|
).then((picture) => {
|
||||||
this.photoOrVideo = false;
|
this.photoOrVideo = false;
|
||||||
let fileObject = {
|
|
||||||
FileBase64: picture,
|
|
||||||
FileExtension: this.removeTextBeforeSlash('jpeg', '/'),
|
|
||||||
OriginalFileName: 'imagem'
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileExtension = this.removeTextBeforeSlash('jpeg', '/')
|
const FileExtension = this.removeTextBeforeSlash('jpeg', '/')
|
||||||
|
|
||||||
@@ -231,11 +228,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
800, // maxHeight
|
800, // maxHeight
|
||||||
0.9 // quality
|
0.9 // quality
|
||||||
).then((picture) => {
|
).then((picture) => {
|
||||||
let fileObject = {
|
|
||||||
FileBase64: picture,
|
|
||||||
FileExtension: this.removeTextBeforeSlash('jpeg', '/'),
|
|
||||||
OriginalFileName: 'image'
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileExtension = this.removeTextBeforeSlash('jpeg', '/')
|
const FileExtension = this.removeTextBeforeSlash('jpeg', '/')
|
||||||
|
|
||||||
@@ -278,7 +270,7 @@ export class NewPublicationPage implements OnInit {
|
|||||||
|
|
||||||
console.log("base64 :data:video/mp4;base64,",this.arrayBufferToBase64(await blob.arrayBuffer())) */
|
console.log("base64 :data:video/mp4;base64,",this.arrayBufferToBase64(await blob.arrayBuffer())) */
|
||||||
|
|
||||||
this.convertBlobToBase64(blobFile.blob).then((value) => {
|
this.convertBlobToBase64(blobFile.blob).then((value: string) => {
|
||||||
|
|
||||||
console.log(value)
|
console.log(value)
|
||||||
|
|
||||||
@@ -294,7 +286,8 @@ export class NewPublicationPage implements OnInit {
|
|||||||
base64: value,
|
base64: value,
|
||||||
extension: FileExtension,
|
extension: FileExtension,
|
||||||
blobFile: file,
|
blobFile: file,
|
||||||
FileType: this.checkFileType.checkFileType(FileExtension)
|
FileType: this.checkFileType.checkFileType(FileExtension) as any,
|
||||||
|
OriginalFileName: 'load video'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -368,7 +361,7 @@ export class NewPublicationPage implements OnInit {
|
|||||||
base64: content.data,
|
base64: content.data,
|
||||||
extension: this.removeTextBeforeSlash(element.mimeType, '/'),
|
extension: this.removeTextBeforeSlash(element.mimeType, '/'),
|
||||||
OriginalFileName: 'video',
|
OriginalFileName: 'video',
|
||||||
FileType: this.checkFileType.checkFileType( this.removeTextBeforeSlash(element.mimeType, '/'))
|
FileType: this.checkFileType.checkFileType( this.removeTextBeforeSlash(element.mimeType, '/')) as any
|
||||||
})
|
})
|
||||||
this.seletedContent.push(fileObject)
|
this.seletedContent.push(fileObject)
|
||||||
})
|
})
|
||||||
@@ -468,11 +461,10 @@ export class NewPublicationPage implements OnInit {
|
|||||||
console.log("this.publication.Files", this.publication.Files)
|
console.log("this.publication.Files", this.publication.Files)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.publication.Files = this.publication.Files.map( (e: PublicationAttachmentEntity) => ({
|
||||||
this.publication.Files = this.publication.Files.map(e => ({
|
FileBase64: e.Base64,
|
||||||
FileBase64: e.FileBase64,
|
|
||||||
FileExtension: e.FileExtension,
|
FileExtension: e.FileExtension,
|
||||||
OriginalFileName: 'foto'
|
OriginalFileName: e.OriginalFileName || 'foto'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -523,23 +515,21 @@ export class NewPublicationPage implements OnInit {
|
|||||||
if(e.FileType == 'video') {
|
if(e.FileType == 'video') {
|
||||||
e.OriginalFileName = e.chucksManager.path
|
e.OriginalFileName = e.chucksManager.path
|
||||||
e.FileExtension = "mp4"
|
e.FileExtension = "mp4"
|
||||||
|
e.Base64 = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return e
|
return e
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log("this.publication.Files", this.publication.Files)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.publication.Files = this.publication.Files.map(e => ({
|
this.publication.Files = this.publication.Files.map( (e:PublicationAttachmentEntity) => ({
|
||||||
FileBase64: e.FileBase64,
|
FileBase64: e.Base64,
|
||||||
FileExtension: e.FileExtension,
|
FileExtension: e.FileExtension,
|
||||||
OriginalFileName: 'foto'
|
OriginalFileName: e.OriginalFileName || 'foto'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loader = this.toastService.loading()
|
const loader = this.toastService.loading()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -560,12 +550,17 @@ export class NewPublicationPage implements OnInit {
|
|||||||
loader.remove()
|
loader.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo")
|
this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.publicationFormMV.ObjectMergeNotification.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.publicationFormMV.ObjectMergeNotification.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
@@ -1071,444 +1066,3 @@ export class NewPublicationPage implements OnInit {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UploadFileUseCase {
|
|
||||||
CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
|
|
||||||
constructor() {}
|
|
||||||
async execute(PublicationAttachmentEntity: PublicationAttachmentEntity): Promise<Result<PublicationAttachmentEntity, PublicationAttachmentEntity>> {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
|
|
||||||
PublicationAttachmentEntity.chucksManager.clearManualRetry()
|
|
||||||
|
|
||||||
let path: string;
|
|
||||||
const length = PublicationAttachmentEntity.chucksManager.chunks.totalChunks.toString()
|
|
||||||
|
|
||||||
const readAndUploadChunk = async(index: number) => {
|
|
||||||
|
|
||||||
const chunk = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(index)
|
|
||||||
const blob = new Blob([chunk]);
|
|
||||||
const blobFile = new File([blob], "test.mp4", { type: blob.type });
|
|
||||||
|
|
||||||
return this.CMAPIService.FileContent({length, path: PublicationAttachmentEntity.chucksManager.path, index, blobFile})
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!PublicationAttachmentEntity.chucksManager.hasPath()) {
|
|
||||||
const initIndex = 1
|
|
||||||
|
|
||||||
const uploadRequest = await readAndUploadChunk(initIndex)
|
|
||||||
|
|
||||||
if(uploadRequest.isOk()) {
|
|
||||||
|
|
||||||
path = uploadRequest.value.data
|
|
||||||
|
|
||||||
PublicationAttachmentEntity.chucksManager.setPath(path)
|
|
||||||
PublicationAttachmentEntity.chucksManager.setResponse(initIndex, uploadRequest)
|
|
||||||
} else {
|
|
||||||
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
|
||||||
return reject(err(PublicationAttachmentEntity))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const allRequest: Promise<any>[] = []
|
|
||||||
let connection = true
|
|
||||||
|
|
||||||
for (let index = 2; ( (index <= PublicationAttachmentEntity.chucksManager.chunks.totalChunks -1) && connection ); index++) {
|
|
||||||
const needUpload = PublicationAttachmentEntity.chucksManager.needToUploadChunkIndex(index)
|
|
||||||
|
|
||||||
if(needUpload) {
|
|
||||||
|
|
||||||
const request = readAndUploadChunk(index).then(async(uploadRequest) => {
|
|
||||||
if(uploadRequest.isErr()) {
|
|
||||||
const pingRequest = await this.CMAPIService.ping()
|
|
||||||
if( pingRequest.isErr()) {
|
|
||||||
connection = false
|
|
||||||
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
|
||||||
return reject(err(PublicationAttachmentEntity))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
allRequest.push(request)
|
|
||||||
|
|
||||||
// const request = readAndUploadChunk(index)
|
|
||||||
// const uploadRequest = await request
|
|
||||||
|
|
||||||
// allRequest.push(request)
|
|
||||||
// if(uploadRequest.isErr()) {
|
|
||||||
// const pingRequest = await this.CMAPIService.ping()
|
|
||||||
// if( pingRequest.isErr()) {
|
|
||||||
// reject(err(PublicationAttachmentEntity))
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!connection) {
|
|
||||||
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
|
||||||
return reject(err(PublicationAttachmentEntity))
|
|
||||||
} else {
|
|
||||||
await Promise.all(allRequest)
|
|
||||||
|
|
||||||
const uploadRequest = await readAndUploadChunk(PublicationAttachmentEntity.chucksManager.chunks.totalChunks)
|
|
||||||
if(uploadRequest.isErr()) {
|
|
||||||
const pingRequest = await this.CMAPIService.ping()
|
|
||||||
if( pingRequest.isErr()) {
|
|
||||||
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
|
||||||
return reject(err(PublicationAttachmentEntity))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PublicationAttachmentEntity.chucksManager.setResponse(PublicationAttachmentEntity.chucksManager.chunks.totalChunks, uploadRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
|
|
||||||
resolve(ok(PublicationAttachmentEntity))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PublicationAttachmentEntity {
|
|
||||||
FileBase64: string
|
|
||||||
FileExtension: string
|
|
||||||
FileType: 'image' | 'video'
|
|
||||||
OriginalFileName: string
|
|
||||||
blobFile: File
|
|
||||||
toUpload = false;
|
|
||||||
chucksManager : ChucksManager
|
|
||||||
|
|
||||||
constructor({base64, extension, blobFile = null, OriginalFileName = null, FileType}) {
|
|
||||||
this.FileBase64 = base64;
|
|
||||||
this.FileExtension = extension;
|
|
||||||
this.blobFile = blobFile
|
|
||||||
this.OriginalFileName = OriginalFileName
|
|
||||||
this.FileType = FileType
|
|
||||||
|
|
||||||
this.fixFileBase64();
|
|
||||||
}
|
|
||||||
|
|
||||||
fixFileBase64() {
|
|
||||||
if(this.FileType == 'image' ) {
|
|
||||||
if(!this.FileBase64.startsWith('data:')) {
|
|
||||||
this.FileBase64 = 'data:image/jpg;base64,' + this.FileBase64
|
|
||||||
}
|
|
||||||
} else if (this.FileType == 'video' ) {
|
|
||||||
if(!this.FileBase64.startsWith('data:') && !this.FileBase64.startsWith('http')) {
|
|
||||||
this.FileBase64 = 'data:video/mp4;base64,' + this.FileBase64
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
needUpload() {
|
|
||||||
this.toUpload = true
|
|
||||||
}
|
|
||||||
|
|
||||||
setChunkManger (chunks: Chunks) {
|
|
||||||
this.chucksManager = new ChucksManager({chunks})
|
|
||||||
}
|
|
||||||
get hasChunkManger() {
|
|
||||||
return this.chucksManager?.chunks
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasChunkManager() {
|
|
||||||
return this.chucksManager != null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IPublicationFormModelEntity {
|
|
||||||
DateIndex: any
|
|
||||||
DocumentId: any
|
|
||||||
ProcessId: any
|
|
||||||
Title: any
|
|
||||||
Message: any
|
|
||||||
DatePublication: any
|
|
||||||
Files: PublicationAttachmentEntity[]
|
|
||||||
}
|
|
||||||
|
|
||||||
class PublicationFormModel implements IPublicationFormModelEntity {
|
|
||||||
constructor() {}
|
|
||||||
DateIndex: any;
|
|
||||||
DocumentId: any;
|
|
||||||
ProcessId: any;
|
|
||||||
Title: any;
|
|
||||||
Message: any;
|
|
||||||
DatePublication: any;
|
|
||||||
OriginalFileName: string;
|
|
||||||
Files: PublicationAttachmentEntity[];
|
|
||||||
|
|
||||||
hasSet = false
|
|
||||||
|
|
||||||
setData(data: IPublicationFormModelEntity) {
|
|
||||||
if(!this.hasSet) {
|
|
||||||
Object.assign(this, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hasSet = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PublicationFormMV {
|
|
||||||
|
|
||||||
private UploadFileUseCase = new UploadFileUseCase()
|
|
||||||
private form = new PublicationFormModel()
|
|
||||||
private ObjectMergeNotification = new ObjectMergeNotification()
|
|
||||||
|
|
||||||
setDataToFrom(data: IPublicationFormModelEntity) {
|
|
||||||
this.form.setData(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private getVideoFiles() {
|
|
||||||
return this.form.Files.filter( x => x.FileType == 'video')
|
|
||||||
}
|
|
||||||
|
|
||||||
private upload(PublicationAttachmentEntity: PublicationAttachmentEntity) {
|
|
||||||
|
|
||||||
return new Promise(async (resolve, reject)=> {
|
|
||||||
|
|
||||||
if(!PublicationAttachmentEntity.hasChunkManger) {
|
|
||||||
const fileBlob = PublicationAttachmentEntity.blobFile;
|
|
||||||
const fileChunks = new Chunks({chunkSize: 500 })
|
|
||||||
fileChunks.setFile(fileBlob)
|
|
||||||
|
|
||||||
PublicationAttachmentEntity.setChunkManger(fileChunks)
|
|
||||||
|
|
||||||
PublicationAttachmentEntity.chucksManager.registerOnLastChunk(()=> {
|
|
||||||
const guid = PublicationAttachmentEntity.chucksManager.path
|
|
||||||
|
|
||||||
this.ObjectMergeNotification.subscribe(guid, (data) => {
|
|
||||||
// console.log("data", data)
|
|
||||||
PublicationAttachmentEntity
|
|
||||||
resolve(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if(PublicationAttachmentEntity.chucksManager.doneUpload) {
|
|
||||||
return resolve(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await this.UploadFileUseCase.execute(PublicationAttachmentEntity)
|
|
||||||
|
|
||||||
if(result.isErr()) {
|
|
||||||
reject(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadVideosFiles(): Promise<Boolean> {
|
|
||||||
return new Promise((resolve, reject)=> {
|
|
||||||
const videosFiles = this.getVideoFiles()
|
|
||||||
|
|
||||||
const videosFilesToUploads = videosFiles.filter( e => e.toUpload == true)
|
|
||||||
|
|
||||||
const Promises: Promise<any>[] = []
|
|
||||||
|
|
||||||
for(const file of videosFilesToUploads) {
|
|
||||||
const promise = this.upload(file)
|
|
||||||
Promises.push(promise)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Promise.all to wait for all promises to resolve
|
|
||||||
Promise.all(Promises)
|
|
||||||
.then((results) => {
|
|
||||||
// Check if every promise resolved successfully
|
|
||||||
const allPromisesResolvedSuccessfully = results.every((result) => result == true);
|
|
||||||
|
|
||||||
if (allPromisesResolvedSuccessfully) {
|
|
||||||
console.log('All promises resolved successfully.');
|
|
||||||
resolve(true)
|
|
||||||
} else {
|
|
||||||
reject(false)
|
|
||||||
console.log('Some promises failed to resolve successfully.');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
reject(false)
|
|
||||||
console.error('An error occurred while resolving promises:', error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Chunks {
|
|
||||||
|
|
||||||
chunkSize: number
|
|
||||||
private file: File
|
|
||||||
|
|
||||||
constructor({chunkSize}) {
|
|
||||||
this.chunkSize = chunkSize * 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChunks () {
|
|
||||||
return Math.ceil(this.file.size / this.chunkSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to read a chunk of the file
|
|
||||||
readChunk(start: number, end: number): Promise<ArrayBuffer> {
|
|
||||||
const file = this.file
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = () => {
|
|
||||||
if (reader.result instanceof ArrayBuffer) {
|
|
||||||
resolve(reader.result);
|
|
||||||
} else {
|
|
||||||
reject(new Error("Failed to read chunk"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.readAsArrayBuffer(file.slice(start, end));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setFile(file: File) {
|
|
||||||
this.file = file
|
|
||||||
}
|
|
||||||
|
|
||||||
async getChunks(i: number) {
|
|
||||||
i--
|
|
||||||
if(i < this.totalChunks) {
|
|
||||||
const start = i * this.chunkSize;
|
|
||||||
const end = Math.min(start + this.chunkSize, this.file.size);
|
|
||||||
const chunk = await this.readChunk(start, end);
|
|
||||||
|
|
||||||
return chunk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IUploadResponse {
|
|
||||||
result: Result<any, Error>
|
|
||||||
attemp: number
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChucksManager {
|
|
||||||
chunks: Chunks
|
|
||||||
uploads: {[key: string]: IUploadResponse } = {}
|
|
||||||
path: string = undefined
|
|
||||||
uploadPercentage: string = "0%"
|
|
||||||
merging = false
|
|
||||||
onSetPath: Function[] = []
|
|
||||||
onSetLastChunk: Function[] = []
|
|
||||||
contentReady = false
|
|
||||||
manualRetry = false
|
|
||||||
|
|
||||||
getUploadPercentage() {
|
|
||||||
return this.uploadPercentage
|
|
||||||
}
|
|
||||||
|
|
||||||
get uploadsCount() {
|
|
||||||
return Object.entries(this.uploads).length
|
|
||||||
}
|
|
||||||
|
|
||||||
get uploadWithSuccessCount() {
|
|
||||||
const uploadWithSuccess = Object.entries(this.uploads).filter(([index, data])=> data.result.isOk())
|
|
||||||
return uploadWithSuccess.length
|
|
||||||
}
|
|
||||||
|
|
||||||
get doneUpload() {
|
|
||||||
return this.chunks.totalChunks == this.uploadWithSuccessCount
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadFunc: Function
|
|
||||||
constructor({chunks}) {
|
|
||||||
this.chunks = chunks
|
|
||||||
}
|
|
||||||
|
|
||||||
calculatePercentage(): number {
|
|
||||||
/**
|
|
||||||
* Calculate the percentage based on the total and current values.
|
|
||||||
*
|
|
||||||
* @param total - The total value.
|
|
||||||
* @param current - The current value.
|
|
||||||
* @returns The percentage calculated as (current / total) * 100.
|
|
||||||
*/
|
|
||||||
const total = this.chunks.totalChunks
|
|
||||||
const current = this.uploadWithSuccessCount
|
|
||||||
|
|
||||||
if (total === 0) {
|
|
||||||
return 0; // To avoid division by zero error
|
|
||||||
}
|
|
||||||
|
|
||||||
const percentage: number = (current / total) * 100;
|
|
||||||
return percentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
setManualRetry() {
|
|
||||||
this.manualRetry = true
|
|
||||||
}
|
|
||||||
|
|
||||||
clearManualRetry() {
|
|
||||||
this.manualRetry = false
|
|
||||||
}
|
|
||||||
|
|
||||||
setPercentage() {
|
|
||||||
const percentage: number = this.calculatePercentage()
|
|
||||||
console.log({percentage})
|
|
||||||
this.uploadPercentage = percentage.toString()+"%"
|
|
||||||
}
|
|
||||||
|
|
||||||
setPath(path: string) {
|
|
||||||
this.path = path
|
|
||||||
this.onSetPath.forEach(callback => callback());
|
|
||||||
}
|
|
||||||
|
|
||||||
registerOnSetPath(a: Function) {
|
|
||||||
this.onSetPath.push(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
registerOnLastChunk(a: Function) {
|
|
||||||
this.onSetPath.push(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
hasPath() {
|
|
||||||
return this.path != undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
isIndexRegistered(index) {
|
|
||||||
if(!this.uploads[index]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
needToUploadChunkIndex(index) {
|
|
||||||
return !this.uploads?.[index]?.result?.isOk()
|
|
||||||
}
|
|
||||||
|
|
||||||
setResponse(index, UploadResponse) {
|
|
||||||
|
|
||||||
if(!this.isIndexRegistered(index)) {
|
|
||||||
this.uploads[index] = {
|
|
||||||
attemp: 1,
|
|
||||||
result: UploadResponse
|
|
||||||
}
|
|
||||||
console.log({UploadResponse})
|
|
||||||
} else {
|
|
||||||
this.uploads[index].attemp++;
|
|
||||||
this.uploads[index].result = UploadResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setPercentage()
|
|
||||||
}
|
|
||||||
|
|
||||||
doneChunkUpload() {
|
|
||||||
this.merging = true
|
|
||||||
this.onSetLastChunk.forEach(callback => callback());
|
|
||||||
}
|
|
||||||
|
|
||||||
contentSetReady() {
|
|
||||||
this.merging = false
|
|
||||||
this.contentReady = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UploadStreamingService } from './upload-streaming.service';
|
||||||
|
|
||||||
|
describe('UploadStreamingService', () => {
|
||||||
|
let service: UploadStreamingService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(UploadStreamingService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,483 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ok, err, Result } from 'neverthrow';
|
||||||
|
import { ObjectMergeNotification } from 'src/app/services/socket-connection-mcr.service';
|
||||||
|
import { CMAPIService } from "src/app/shared/repository/CMAPI/cmapi.service"
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class UploadStreamingService {
|
||||||
|
constructor( private CMAPIService: CMAPIService,) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UploadFileUseCase {
|
||||||
|
CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
|
||||||
|
constructor() {}
|
||||||
|
async execute(PublicationAttachmentEntity: PublicationAttachmentEntity): Promise<Result<PublicationAttachmentEntity, PublicationAttachmentEntity>> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
|
||||||
|
PublicationAttachmentEntity.chucksManager.clearManualRetry()
|
||||||
|
|
||||||
|
let path: string;
|
||||||
|
const length = PublicationAttachmentEntity.chucksManager.chunks.totalChunks.toString()
|
||||||
|
|
||||||
|
const readAndUploadChunk = async(index: number) => {
|
||||||
|
|
||||||
|
const chunk = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(index)
|
||||||
|
const blob = new Blob([chunk]);
|
||||||
|
const blobFile = new File([blob], "test.mp4", { type: blob.type });
|
||||||
|
|
||||||
|
return this.CMAPIService.FileContent({length, path: PublicationAttachmentEntity.chucksManager.path, index, blobFile})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PublicationAttachmentEntity.chucksManager.hasPath()) {
|
||||||
|
const initIndex = 1
|
||||||
|
|
||||||
|
const uploadRequest = await readAndUploadChunk(initIndex)
|
||||||
|
|
||||||
|
if(uploadRequest.isOk()) {
|
||||||
|
|
||||||
|
path = uploadRequest.value.data
|
||||||
|
|
||||||
|
PublicationAttachmentEntity.chucksManager.setPath(path)
|
||||||
|
PublicationAttachmentEntity.chucksManager.setResponse(initIndex, uploadRequest)
|
||||||
|
} else {
|
||||||
|
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
||||||
|
return reject(err(PublicationAttachmentEntity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const allRequest: Promise<any>[] = []
|
||||||
|
let connection = true
|
||||||
|
|
||||||
|
for (let index = 2; ( (index <= PublicationAttachmentEntity.chucksManager.chunks.totalChunks -1) && connection ); index++) {
|
||||||
|
const needUpload = PublicationAttachmentEntity.chucksManager.needToUploadChunkIndex(index)
|
||||||
|
|
||||||
|
if(needUpload) {
|
||||||
|
|
||||||
|
const request = readAndUploadChunk(index).then(async(uploadRequest) => {
|
||||||
|
if(uploadRequest.isErr()) {
|
||||||
|
const pingRequest = await this.CMAPIService.ping()
|
||||||
|
if( pingRequest.isErr()) {
|
||||||
|
connection = false
|
||||||
|
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
||||||
|
return reject(err(PublicationAttachmentEntity))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
allRequest.push(request)
|
||||||
|
|
||||||
|
// const request = readAndUploadChunk(index)
|
||||||
|
// const uploadRequest = await request
|
||||||
|
|
||||||
|
// allRequest.push(request)
|
||||||
|
// if(uploadRequest.isErr()) {
|
||||||
|
// const pingRequest = await this.CMAPIService.ping()
|
||||||
|
// if( pingRequest.isErr()) {
|
||||||
|
// reject(err(PublicationAttachmentEntity))
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!connection) {
|
||||||
|
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
||||||
|
return reject(err(PublicationAttachmentEntity))
|
||||||
|
} else {
|
||||||
|
await Promise.all(allRequest)
|
||||||
|
|
||||||
|
const uploadRequest = await readAndUploadChunk(PublicationAttachmentEntity.chucksManager.chunks.totalChunks)
|
||||||
|
if(uploadRequest.isErr()) {
|
||||||
|
const pingRequest = await this.CMAPIService.ping()
|
||||||
|
if( pingRequest.isErr()) {
|
||||||
|
PublicationAttachmentEntity.chucksManager.setManualRetry()
|
||||||
|
return reject(err(PublicationAttachmentEntity))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PublicationAttachmentEntity.chucksManager.setResponse(PublicationAttachmentEntity.chucksManager.chunks.totalChunks, uploadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
|
||||||
|
resolve(ok(PublicationAttachmentEntity))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PublicationAttachmentEntity {
|
||||||
|
url: string
|
||||||
|
FileExtension: string
|
||||||
|
FileType: 'image' | 'video'
|
||||||
|
OriginalFileName: string
|
||||||
|
blobFile?: File
|
||||||
|
toUpload = false;
|
||||||
|
chucksManager : ChucksManager
|
||||||
|
Base64: string
|
||||||
|
|
||||||
|
constructor({base64, extension, blobFile, OriginalFileName, FileType}:PublicationAttachmentEntityParams) {
|
||||||
|
this.Base64 = base64;
|
||||||
|
this.FileExtension = extension;
|
||||||
|
this.blobFile = blobFile
|
||||||
|
this.OriginalFileName = OriginalFileName
|
||||||
|
this.FileType = FileType
|
||||||
|
|
||||||
|
this.fixFileBase64();
|
||||||
|
}
|
||||||
|
|
||||||
|
fixFileBase64() {
|
||||||
|
if(this.FileType == 'image' ) {
|
||||||
|
if(!this.Base64.startsWith('data:')) {
|
||||||
|
this.url = 'data:image/jpg;base64,' + this.Base64
|
||||||
|
} else {
|
||||||
|
this.url = this.Base64
|
||||||
|
}
|
||||||
|
} else if (this.FileType == 'video' ) {
|
||||||
|
if(!this.Base64.startsWith('data:') && !this.Base64.startsWith('http')) {
|
||||||
|
this.url = 'data:video/mp4;base64,' + this.Base64
|
||||||
|
} else {
|
||||||
|
this.url = this.Base64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
needUpload() {
|
||||||
|
this.toUpload = true
|
||||||
|
}
|
||||||
|
|
||||||
|
setChunkManger (chunks: Chunks) {
|
||||||
|
this.chucksManager = new ChucksManager({chunks})
|
||||||
|
}
|
||||||
|
get hasChunkManger() {
|
||||||
|
return this.chucksManager?.chunks
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasChunkManager() {
|
||||||
|
return this.chucksManager != null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IPublicationFormModelEntity {
|
||||||
|
DateIndex: any
|
||||||
|
DocumentId: any
|
||||||
|
ProcessId: any
|
||||||
|
Title: any
|
||||||
|
Message: any
|
||||||
|
DatePublication: any
|
||||||
|
Files: PublicationAttachmentEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PublicationAttachmentEntityParams {
|
||||||
|
base64: string,
|
||||||
|
blobFile?: File
|
||||||
|
extension: string,
|
||||||
|
OriginalFileName: string,
|
||||||
|
FileType: 'image' | 'video'
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PublicationFormModel implements IPublicationFormModelEntity {
|
||||||
|
constructor() {}
|
||||||
|
DateIndex: any;
|
||||||
|
DocumentId: any;
|
||||||
|
ProcessId: any;
|
||||||
|
Title: any;
|
||||||
|
Message: any;
|
||||||
|
DatePublication: any;
|
||||||
|
OriginalFileName: string;
|
||||||
|
Files: PublicationAttachmentEntity[];
|
||||||
|
|
||||||
|
hasSet = false
|
||||||
|
|
||||||
|
setData(data: IPublicationFormModelEntity) {
|
||||||
|
if(!this.hasSet) {
|
||||||
|
Object.assign(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasSet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PublicationFormMV {
|
||||||
|
|
||||||
|
private UploadFileUseCase = new UploadFileUseCase()
|
||||||
|
private form = new PublicationFormModel()
|
||||||
|
ObjectMergeNotification = new ObjectMergeNotification()
|
||||||
|
|
||||||
|
setDataToFrom(data: IPublicationFormModelEntity) {
|
||||||
|
this.form.setData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private getVideoFiles() {
|
||||||
|
return this.form.Files.filter( x => x.FileType == 'video')
|
||||||
|
}
|
||||||
|
|
||||||
|
private upload(PublicationAttachmentEntity: PublicationAttachmentEntity) {
|
||||||
|
|
||||||
|
return new Promise(async (resolve, reject)=> {
|
||||||
|
|
||||||
|
if(!PublicationAttachmentEntity.hasChunkManger) {
|
||||||
|
const fileBlob = PublicationAttachmentEntity.blobFile;
|
||||||
|
const fileChunks = new Chunks({chunkSize: 500 })
|
||||||
|
fileChunks.setFile(fileBlob)
|
||||||
|
|
||||||
|
PublicationAttachmentEntity.setChunkManger(fileChunks)
|
||||||
|
|
||||||
|
PublicationAttachmentEntity.chucksManager.registerOnLastChunk(()=> {
|
||||||
|
const guid = PublicationAttachmentEntity.chucksManager.path
|
||||||
|
|
||||||
|
this.ObjectMergeNotification.subscribe(guid, (data) => {
|
||||||
|
// console.log("data", data)
|
||||||
|
PublicationAttachmentEntity
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(PublicationAttachmentEntity.chucksManager.doneUpload) {
|
||||||
|
return resolve(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( PublicationAttachmentEntity.chucksManager.isUploading == false) {
|
||||||
|
PublicationAttachmentEntity.chucksManager.setUploading()
|
||||||
|
const result = await this.UploadFileUseCase.execute(PublicationAttachmentEntity)
|
||||||
|
PublicationAttachmentEntity.chucksManager.clearUploading()
|
||||||
|
|
||||||
|
if(result.isErr()) {
|
||||||
|
reject(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadVideosFiles(): Promise<Boolean> {
|
||||||
|
return new Promise((resolve, reject)=> {
|
||||||
|
const videosFiles = this.getVideoFiles()
|
||||||
|
|
||||||
|
const videosFilesToUploads = videosFiles.filter( e => e.FileType == "video")
|
||||||
|
|
||||||
|
const Promises: Promise<any>[] = []
|
||||||
|
|
||||||
|
for(const file of videosFilesToUploads) {
|
||||||
|
const promise = this.upload(file)
|
||||||
|
Promises.push(promise)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Promise.all to wait for all promises to resolve
|
||||||
|
Promise.all(Promises)
|
||||||
|
.then((results) => {
|
||||||
|
// Check if every promise resolved successfully
|
||||||
|
const allPromisesResolvedSuccessfully = results.every((result) => result == true);
|
||||||
|
|
||||||
|
if (allPromisesResolvedSuccessfully) {
|
||||||
|
console.log('All promises resolved successfully.');
|
||||||
|
resolve(true)
|
||||||
|
} else {
|
||||||
|
reject(false)
|
||||||
|
console.log('Some promises failed to resolve successfully.');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(false)
|
||||||
|
console.error('An error occurred while resolving promises:', error);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class Chunks {
|
||||||
|
|
||||||
|
chunkSize: number
|
||||||
|
private file: File
|
||||||
|
|
||||||
|
constructor({chunkSize}) {
|
||||||
|
this.chunkSize = chunkSize * 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalChunks () {
|
||||||
|
return Math.ceil(this.file.size / this.chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to read a chunk of the file
|
||||||
|
readChunk(start: number, end: number): Promise<ArrayBuffer> {
|
||||||
|
const file = this.file
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
if (reader.result instanceof ArrayBuffer) {
|
||||||
|
resolve(reader.result);
|
||||||
|
} else {
|
||||||
|
reject(new Error("Failed to read chunk"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsArrayBuffer(file.slice(start, end));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setFile(file: File) {
|
||||||
|
this.file = file
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChunks(i: number) {
|
||||||
|
i--
|
||||||
|
if(i < this.totalChunks) {
|
||||||
|
const start = i * this.chunkSize;
|
||||||
|
const end = Math.min(start + this.chunkSize, this.file.size);
|
||||||
|
const chunk = await this.readChunk(start, end);
|
||||||
|
|
||||||
|
return chunk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IUploadResponse {
|
||||||
|
result: Result<any, Error>
|
||||||
|
attemp: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChucksManager {
|
||||||
|
chunks: Chunks
|
||||||
|
uploads: {[key: string]: IUploadResponse } = {}
|
||||||
|
path: string = undefined
|
||||||
|
uploadPercentage: string = "0%"
|
||||||
|
merging = false
|
||||||
|
onSetPath: Function[] = []
|
||||||
|
onSetLastChunk: Function[] = []
|
||||||
|
contentReady = false
|
||||||
|
manualRetry = false
|
||||||
|
isUploading = false
|
||||||
|
subscribeToUseCaseResponse: Function[] = []
|
||||||
|
|
||||||
|
getUploadPercentage() {
|
||||||
|
return this.uploadPercentage
|
||||||
|
}
|
||||||
|
|
||||||
|
get uploadsCount() {
|
||||||
|
return Object.entries(this.uploads).length
|
||||||
|
}
|
||||||
|
|
||||||
|
get uploadWithSuccessCount() {
|
||||||
|
const uploadWithSuccess = Object.entries(this.uploads).filter(([index, data])=> data.result.isOk())
|
||||||
|
return uploadWithSuccess.length
|
||||||
|
}
|
||||||
|
|
||||||
|
get doneUpload() {
|
||||||
|
return this.chunks.totalChunks == this.uploadWithSuccessCount
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFunc: Function
|
||||||
|
constructor({chunks}) {
|
||||||
|
this.chunks = chunks
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatePercentage(): number {
|
||||||
|
/**
|
||||||
|
* Calculate the percentage based on the total and current values.
|
||||||
|
*
|
||||||
|
* @param total - The total value.
|
||||||
|
* @param current - The current value.
|
||||||
|
* @returns The percentage calculated as (current / total) * 100.
|
||||||
|
*/
|
||||||
|
const total = this.chunks.totalChunks
|
||||||
|
const current = this.uploadWithSuccessCount
|
||||||
|
|
||||||
|
if (total === 0) {
|
||||||
|
return 0; // To avoid division by zero error
|
||||||
|
}
|
||||||
|
|
||||||
|
const percentage: number = (current / total) * 100;
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
setManualRetry() {
|
||||||
|
this.manualRetry = true
|
||||||
|
}
|
||||||
|
|
||||||
|
clearManualRetry() {
|
||||||
|
this.manualRetry = false
|
||||||
|
}
|
||||||
|
|
||||||
|
setUploading() {
|
||||||
|
this.isUploading = true
|
||||||
|
}
|
||||||
|
clearUploading() {
|
||||||
|
this.isUploading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
setPercentage() {
|
||||||
|
const percentage: number = this.calculatePercentage()
|
||||||
|
console.log({percentage})
|
||||||
|
this.uploadPercentage = percentage.toString()+"%"
|
||||||
|
}
|
||||||
|
|
||||||
|
setPath(path: string) {
|
||||||
|
this.path = path
|
||||||
|
this.onSetPath.forEach(callback => callback());
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnSetPath(a: Function) {
|
||||||
|
this.onSetPath.push(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnLastChunk(a: Function) {
|
||||||
|
this.onSetPath.push(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
registerToUseCaseResponse(a: Function) {
|
||||||
|
this.subscribeToUseCaseResponse.push(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hasPath() {
|
||||||
|
return this.path != undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
isIndexRegistered(index) {
|
||||||
|
if(!this.uploads[index]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
needToUploadChunkIndex(index) {
|
||||||
|
return !this.uploads?.[index]?.result?.isOk()
|
||||||
|
}
|
||||||
|
|
||||||
|
setResponse(index, UploadResponse) {
|
||||||
|
|
||||||
|
if(!this.isIndexRegistered(index)) {
|
||||||
|
this.uploads[index] = {
|
||||||
|
attemp: 1,
|
||||||
|
result: UploadResponse
|
||||||
|
}
|
||||||
|
console.log({UploadResponse})
|
||||||
|
} else {
|
||||||
|
this.uploads[index].attemp++;
|
||||||
|
this.uploads[index].result = UploadResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setPercentage()
|
||||||
|
}
|
||||||
|
|
||||||
|
doneChunkUpload() {
|
||||||
|
this.merging = true
|
||||||
|
this.onSetLastChunk.forEach(callback => callback());
|
||||||
|
}
|
||||||
|
|
||||||
|
contentSetReady() {
|
||||||
|
this.merging = false
|
||||||
|
this.contentReady = true
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user