video uploader

This commit is contained in:
Peter Maquiran
2024-01-29 13:49:53 +01:00
parent 892bdbe5cf
commit 2605d73baa
11 changed files with 757 additions and 179 deletions
+1 -1
View File
@@ -11,4 +11,4 @@ export class Publication{
Files:any = [];
FileExtension?: string;
OrganicEntityId?: number;
}
}
@@ -1,24 +1,31 @@
import { Injectable } from '@angular/core';
import * as signalR from "@microsoft/signalr"
import { SessionStore } from '../store/session.service';
import { v4 as uuidv4 } from 'uuid'
import { HttpClient, HttpHeaders, HttpEventType } from '@angular/common/http';
import { CMAPIService } from '../shared/repository/CMAPI/cmapi.service';
import { HubConnectionBuilder } from '@microsoft/signalr';
@Injectable({
providedIn: 'root'
})
export class SocketConnectionMCRService {
private callbacks: Function[] = []
private onDisconnect: Function[] = []
private onConnect: Function[] = []
constructor() { }
constructor(private http: HttpClient,) {
window["http"] = this.http
}
connect() {
var connection = new signalR.HubConnectionBuilder()
.withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
accessTokenFactory: () => SessionStore.user.Authorization
accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
}).configureLogging(signalR.LogLevel.Information)
.build();
connection.on("ReceiveMessage", (message) => {
console.log("ReceiveMessage", message)
})
@@ -43,4 +50,319 @@ export class SocketConnectionMCRService {
}
subscribe(callback) {
this.callbacks.push(callback);
}
unsubscribe(callback) {
this.callbacks = this.callbacks.filter(cb => cb !== callback);
}
onDisconnectCallback(callback) {
this.onDisconnect.push(callback)
}
onConnectCallback(callback) {
this.onConnect.push(callback)
}
}
class ReconnectingWebSocketSignalR {
private connection: any
isOpen: boolean
private callbacks: Function[] = []
private onDisconnect: Function[] = []
private onConnect: Function[] = []
constructor() {
this.isOpen = false;
this.connect();
}
connect() {
this.connection = new signalR.HubConnectionBuilder()
.withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
}).configureLogging(signalR.LogLevel.Information)
.build();
this.connection.start()
.then(() => {
this.isOpen = true;
console.log('WebSocket connection established');
this.onConnect.forEach(callback => callback());
console.log("SignalR connection started.");
})
.catch((error) => {
console.error("Error starting SignalR connection:", error);
});
this.connection.on("ReceiveMessage", (message) => {
const data: any = JSON.parse(message)
console.log(data)
this.callbacks.forEach(callback => callback(data));
})
this.connection.onclose((error) => {
console.log('WebSocket connection closed');
this.isOpen = false;
this.onDisconnect.forEach(callback => callback());
// Attempt to reconnect after a delay
setTimeout(() => {
this.connect();
}, 1000); // Adjust the delay as needed
});
}
subscribe(callback) {
this.callbacks.push(callback);
}
unsubscribe(callback) {
this.callbacks = this.callbacks.filter(cb => cb !== callback);
}
onDisconnectCallback(callback) {
this.onDisconnect.push(callback)
}
onConnectCallback(callback) {
this.onConnect.push(callback)
}
}
interface socketResponse {
index: string
Guid: string
isCompleted: Boolean
}
class ReconnectingWebSocket {
private url: string
private socket
isOpen: boolean
private callbacks: Function[] = []
private onDisconnect: Function[] = []
private onConnect: Function[] = []
http: HttpClient = window["http"]
constructor(url) {
this.url = url;
this.socket = null;
this.isOpen = false;
this.connect();
}
connect() {
this.socket = new WebSocket(this.url);
this.socket.addEventListener('open', (event) => {
this.isOpen = true;
console.log('WebSocket connection established');
// Example: Send a message to the server
this.socket.send('Hello, WebSocket Server!');
this.onConnect.forEach(callback => callback());
});
this.socket.addEventListener('message', (event) => {
const data: socketResponse = JSON.parse(event.data)
this.callbacks.forEach(callback => callback(data));
});
this.socket.addEventListener('close', (event) => {
console.log('WebSocket connection closed');
this.isOpen = false;
this.onDisconnect.forEach(callback => callback());
// Attempt to reconnect after a delay
setTimeout(() => {
this.connect();
}, 1000); // Adjust the delay as needed
});
}
send(message) {
if (this.isOpen) {
this.socket.send(message);
} else {
console.error('WebSocket connection is not open. Unable to send message.');
}
}
close() {
if (this.isOpen) {
this.socket.close();
}
}
subscribe(callback) {
this.callbacks.push(callback);
}
unsubscribe(callback) {
this.callbacks = this.callbacks.filter(cb => cb !== callback);
}
onDisconnectCallback(callback) {
this.onDisconnect.push(callback)
}
onConnectCallback(callback) {
this.onConnect.push(callback)
}
}
// export class ObjectMergeNotification{
// //socket = new ReconnectingWebSocket('ws://localhost:3002');
// callbacks: {[GUID: string]: Function} = {}
// runWatch = true
// CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
// constructor() {
// // this.socket.onDisconnectCallback(()=> {
// // this.runWatch = true
// // this.watch()
// // })
// // this.socket.onConnectCallback(()=> {
// // this.runWatch = false
// // })
// // this.socket.subscribe((data: socketResponse) => {
// // if(data.isCompleted == true) {
// // this.callbacks[data.Guid](data)
// // delete this.callbacks[data.Guid]
// // }
// // })
// this.watch()
// }
// async watch() {
// if(this.runWatch) {
// setTimeout(async ()=> {
// for(const [key, funx] of Object.entries(this.callbacks)) {
// const request = await this.CMAPIService.getVideoHeader(key)
// if(request.isOk()) {
// funx()
// delete this.callbacks[key]
// }
// }
// this.watch()
// }, 1000)
// }
// }
// subscribe(GUID, callback:Function) {
// this.callbacks[GUID] = callback;
// }
// unsubscribe(GUID) {
// delete this.callbacks[GUID]
// }
// }
export class ObjectMergeNotification{
socket = new ReconnectingWebSocketSignalR()
callbacks: {[GUID: string]: Function} = {}
runWatch = true
CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
constructor() {
this.socket.onDisconnectCallback(()=> {
this.runWatch = true
this.watch()
})
this.socket.onConnectCallback(()=> {
this.runWatch = false
})
this.socket.subscribe((data: socketResponse) => {
if(data.isCompleted == true) {
this.callbacks[data.Guid](data)
delete this.callbacks[data.Guid]
}
})
this.watch()
}
connect() {
var connection = new signalR.HubConnectionBuilder()
.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() {
if(this.runWatch) {
setTimeout(async ()=> {
for(const [key, funx] of Object.entries(this.callbacks)) {
const request = await this.CMAPIService.getVideoHeader(key)
if(request.isOk()) {
funx()
delete this.callbacks[key]
}
}
this.watch()
}, 1000)
}
}
subscribe(GUID, callback:Function) {
this.callbacks[GUID] = callback;
}
unsubscribe(GUID) {
delete this.callbacks[GUID]
}
}
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { CMAPIAPIService } from './cmapi-api.service';
describe('CMAPIAPIService', () => {
let service: CMAPIAPIService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(CMAPIAPIService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,18 @@
import { Injectable } from '@angular/core';
import { HttpServiceService } from 'src/app/services/http/http-service.service';
import { HttpClient, HttpEvent, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CMAPIAPIService {
constructor( private HttpServiceService: HttpServiceService,
private http: HttpClient,) { }
getVideoHeader(url: string) {
return this.http.head('http://localhost:3001/static/'+url, { observe: 'response' })
}
}
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { CMAPIService } from './cmapi.service';
describe('CMAPIService', () => {
let service: CMAPIService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(CMAPIService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
+21
View File
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { HttpServiceService } from 'src/app/services/http/http-service.service';
import { HttpClient, HttpEvent, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CMAPIService {
constructor( private HttpServiceService: HttpServiceService,
private http: HttpClient,) {
window["CMAPIService"] = this
}
getVideoHeader(url: string): Observable<Boolean> {
return this.http.head(url, { observe: 'response' })
.map(response => response.status === 200)
.catch(() => Observable.of(false));
}
}
@@ -158,7 +158,7 @@ export class MiddlewareServiceService {
// ===========================================================================
CMAPIFileContent({length, path, index, blobFile}) {
CMAPIPing() {
const headers = new HttpHeaders();
headers.set('Authorization', 'Bearer ' + SessionStore.user.Authorization);
@@ -170,6 +170,31 @@ export class MiddlewareServiceService {
};
const formData = new FormData();
formData.append("blobFile", "blobFile");
formData.append("length", "length");
formData.append("index", "index.toString(");
return this.http.post<IuploadFileLK>(`${geturl}`, formData, options)
}
CMAPIFileContent({length, path, index, blobFile}) {
const headers = new HttpHeaders();
headers.set('Authorization', 'Bearer ' + SessionStore.user.Authorization);
// const geturl = 'http://localhost:3001/FileHub';
// const geturl = environment.apiURL + 'Tasks/DelegateTask';
const geturl = environment.apiPCURL + 'FileContent';
let options = {
headers: headers
};
const formData = new FormData();
formData.append("blobFile", blobFile);
@@ -182,4 +207,15 @@ export class MiddlewareServiceService {
return this.http.post<IuploadFileLK>(`${geturl}`, formData, options)
}
tryToReachTheServer() {
let opts = {
headers: {},
}
return this.http.post(environment.apiURL + "UserAuthentication/Login", '', opts)
}
}
@@ -62,13 +62,19 @@
<div class="progress-bar" id="myProgressBar"></div>
</div> -->
<!-- <div *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video'">
<div *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && seleted.chucksManager">
<mat-progress-bar
*ngIf="seleted.chucksManager"
mode="determinate"
style="width: 50%"
></mat-progress-bar>
</div> -->
mode="determinate"
[style.width]="seleted.chucksManager.uploadPercentage"
></mat-progress-bar>
</div>
<video *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video'" width="70" height="70"
preload="metadata" webkit-playsinline="webkit-playsinline">
@@ -14,8 +14,10 @@ import { FileValidatorService } from "src/app/services/file/file-validator.servi
import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service";
import { LakefsRepositoryService } from '../../repository/lakefs/lakefs-repository.service';
import { ok, err, Result } from 'neverthrow';
import { SocketConnectionMCRService } from "src/app/services/socket-connection-mcr.service"
import { CMAPIService } from "src/app/shared/repository/CMAPI/cmapi.service";
import { ObjectMergeNotification, SocketConnectionMCRService } from "src/app/services/socket-connection-mcr.service"
import { CMAPIService } from '../../repository/CMAPI/cmapi.service';
import { environment } from 'src/environments/environment';
enum ActionType {
newRapid = "1",
@@ -338,6 +340,7 @@ export class NewPublicationPage implements OnInit {
}
if(this.seletedContent.length == 0) {
const newAttachment = new PublicationAttachmentEntity(
@@ -356,6 +359,7 @@ export class NewPublicationPage implements OnInit {
if (this.publicationType == ActionType.edit) {
if (this.seletedContent.length >= 1) {
const loader = this.toastService.loading()
@@ -370,6 +374,22 @@ export class NewPublicationPage implements OnInit {
}
this.publicationFormMV.setDataToFrom(this.publication)
const upload = await this.publicationFormMV.uploadVideosFiles()
if(upload) {
this.publication.Files = this.publication.Files.map((e:PublicationAttachmentEntity)=> {
if(e.FileType == 'video') {
e.FileBase64 = environment.apiURL + "/ObjectServer/StreamFiles?path="+ e.chucksManager.path
}
return e
})
console.log("this.publication.Files", this.publication.Files)
}
this.publication.Files = this.publication.Files.map( e => ({
FileBase64: e.FileBase64,
FileExtension: e.FileExtension,
@@ -416,6 +436,20 @@ export class NewPublicationPage implements OnInit {
}
this.publicationFormMV.setDataToFrom(this.publication)
const upload = await this.publicationFormMV.uploadVideosFiles()
if(upload) {
this.publication.Files = this.publication.Files.map((e:PublicationAttachmentEntity)=> {
if(e.FileType == 'video') {
e.FileBase64 = environment.apiURL + "/ObjectServer/StreamFiles?path="+ e.chucksManager.path
}
return e
})
console.log("this.publication.Files", this.publication.Files)
}
this.publication.Files = this.publication.Files.map( e => ({
FileBase64: e.FileBase64,
@@ -871,7 +905,7 @@ export class NewPublicationPage implements OnInit {
uploadChunk() {
async uploadChunk() {
let time = new Date()
this.publication = {
@@ -886,162 +920,95 @@ export class NewPublicationPage implements OnInit {
}
this.publicationFormMV.setDataToFrom(this.publication)
this.publicationFormMV.uploadVideosFiles()
}
}
// class UploadFileUseCase {
// LakefsRepositoryService: LakefsRepositoryService = window["LakefsRepositoryService"]
// constructor() {}
// execute(attachment: PublicationAttachmentEntity) {
// const file: File = attachment.blob
// const chunkSize = 1024 * 100; // Adjust the chunk size as needed
// const fileSize = file.size;
// let uploadedSize = 0
// const totalChunks = Math.ceil(fileSize / chunkSize);
// let offset = 0;
// let i = 1;
// let j = 0;
// let path;
// function count () {
// j++
// return j
// }
// const readAndUploadChunk = async(index: number) => {
// return new Promise<void>((resolve, reject) => {
// const chunk = file.slice(offset, offset + chunkSize);
// const reader = new FileReader();
// reader.onload = async () => {
// const blob = new Blob([reader.result as ArrayBuffer]);
// const formData = new FormData();
// const file = new File([blob], "test.mp4", { type: blob.type });
// uploadedSize =+ file.size
// formData.append("blobFile", file);
// formData.append("length", totalChunks.toString());
// formData.append("index", index.toString());
// formData.append("path", path);
// try {
// const response = await this.LakefsRepositoryService.uploadFile(formData).toPromise()
// console.log({response})
// resolve()
// } catch (erro) {
// reject()
// }
// };
// reader.readAsArrayBuffer(chunk);
// offset += chunkSize;
// });
// }
// const loop = async() => {
// for (let index = 2; index <= totalChunks; index++) {
// await readAndUploadChunk(index);
// }
// }
// const startUpload = async() => {
// const index = count();
// const chunk = file.slice(offset, offset + chunkSize);
// const reader = new FileReader();
// reader.onload = async () => {
// const blob = new Blob([reader.result as ArrayBuffer]);
// const formData = new FormData();
// const file = new File([blob], "test.mp4", { type: blob.type });
// uploadedSize =+ file.size
// formData.append("blobFile", file);
// formData.append("length", totalChunks.toString());
// formData.append("index", index.toString());
// const response: any = await this.LakefsRepositoryService.uploadFile(formData).toPromise()
// console.log({ response, index });
// if (index === 1) {
// path = response.path;
// }
// await loop();
// };
// reader.readAsArrayBuffer(chunk);
// offset += chunkSize;
// }
// startUpload();
// }
// }
class UploadFileUseCase {
CMAPIService: CMAPIService = window["CMAPIService"]
CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
constructor() {}
async execute(ChucksManager: ChucksManager): Promise<Result<ChucksManager, ChucksManager>> {
async execute(PublicationAttachmentEntity: PublicationAttachmentEntity): Promise<Result<PublicationAttachmentEntity, PublicationAttachmentEntity>> {
return new Promise(async (resolve, reject) => {
let path: string;
const length = ChucksManager.chunks.totalChunks.toString()
const readAndUploadChunk = async(index: number) => {
let path: string;
const length = PublicationAttachmentEntity.chucksManager.chunks.totalChunks.toString()
const chunk = await ChucksManager.chunks.getChunks(index)
const blob = new Blob([chunk]);
const blobFile = new File([blob], "test.mp4", { type: blob.type });
const readAndUploadChunk = async(index: number) => {
return await this.CMAPIService.FileContent({length, path: ChucksManager.path, index, blobFile})
}
const chunk = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(index)
const blob = new Blob([chunk]);
const blobFile = new File([blob], "test.mp4", { type: blob.type });
if(!ChucksManager.hasPath()) {
const initIndex = ChucksManager.uploadsCount + 1
const chuck = await ChucksManager.chunks.getChunks(initIndex)
const blob = new Blob([chuck]);
const blobFile = new File([blob], "test.mp4", { type: blob.type });
const uploadRequest = await this.CMAPIService.FileContent({length, path:ChucksManager.path, index: initIndex, blobFile})
if(uploadRequest.isOk()) {
path = uploadRequest.value.data
ChucksManager.setPath(path)
ChucksManager.setResponse(initIndex, uploadRequest.value as any)
} else {
return err(ChucksManager)
return await this.CMAPIService.FileContent({length, path: PublicationAttachmentEntity.chucksManager.path, index, blobFile})
}
}
const indexContinuation = ChucksManager.uploadsCount + 1
for (let index = indexContinuation; index <= ChucksManager.chunks.totalChunks; index++) {
const uploadRequest = await readAndUploadChunk(index)
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 {
reject(err(PublicationAttachmentEntity))
}
}
const allRequest: Promise<any>[] = []
for (let index = 2; index <= PublicationAttachmentEntity.chucksManager.chunks.totalChunks -1; 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()) {
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)
// }
}
}
await Promise.all(allRequest)
const uploadRequest = await readAndUploadChunk(PublicationAttachmentEntity.chucksManager.chunks.totalChunks)
if(uploadRequest.isErr()) {
return err(ChucksManager)
const pingRequest = await this.CMAPIService.ping()
if( pingRequest.isErr()) {
reject(err(PublicationAttachmentEntity))
}
} else {
ChucksManager.setResponse(index, uploadRequest.value as any)
PublicationAttachmentEntity.chucksManager.setResponse(PublicationAttachmentEntity.chucksManager.chunks.totalChunks, uploadRequest)
}
}
return ok(ChucksManager)
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
resolve(ok(PublicationAttachmentEntity))
})
}
}
@@ -1084,6 +1051,9 @@ class PublicationAttachmentEntity {
setChunkManger (chunks: Chunks) {
this.chucksManager = new ChucksManager({chunks})
}
get hasChunkManger() {
return this.chucksManager?.chunks
}
get hasChunkManager() {
return this.chucksManager != null
@@ -1111,8 +1081,14 @@ class PublicationFormModel implements IPublicationFormModelEntity {
OriginalFileName: string;
Files: PublicationAttachmentEntity[];
hasSet = false
setData(data: IPublicationFormModelEntity) {
Object.assign(this, data)
if(!this.hasSet) {
Object.assign(this, data)
}
this.hasSet = true
}
}
@@ -1120,6 +1096,7 @@ class PublicationFormMV {
private UploadFileUseCase = new UploadFileUseCase()
private form = new PublicationFormModel()
private ObjectMergeNotification = new ObjectMergeNotification()
setDataToFrom(data: IPublicationFormModelEntity) {
this.form.setData(data)
@@ -1129,30 +1106,76 @@ class PublicationFormMV {
return this.form.Files.filter( x => x.FileType == 'video')
}
private async upload(PublicationAttachmentEntity: PublicationAttachmentEntity) {
private upload(PublicationAttachmentEntity: PublicationAttachmentEntity) {
const fileBlob = PublicationAttachmentEntity.blobFile;
const fileChunks = new Chunks({chunkSize: 100 })
fileChunks.setFile(fileBlob)
return new Promise(async (resolve, reject)=> {
PublicationAttachmentEntity.setChunkManger(fileChunks)
if(!PublicationAttachmentEntity.hasChunkManger) {
const fileBlob = PublicationAttachmentEntity.blobFile;
const fileChunks = new Chunks({chunkSize: 500 })
fileChunks.setFile(fileBlob)
const ChucksManagers = new ChucksManager({chunks: fileChunks})
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)
}
})
this.UploadFileUseCase.execute(ChucksManagers)
}
uploadVideosFiles() {
uploadVideosFiles(): Promise<Boolean> {
return new Promise((resolve, reject)=> {
const videosFiles = this.getVideoFiles()
const videosFiles = this.getVideoFiles()
const videosFilesToUploads = videosFiles.filter( e => e.toUpload == true)
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);
});
})
for(const file of videosFilesToUploads) {
this.upload(file)
}
}
}
@@ -1205,7 +1228,7 @@ class Chunks {
}
interface IUploadResponse {
result: Result<string, Error>
result: Result<any, Error>
attemp: number
}
@@ -1213,25 +1236,110 @@ class ChucksManager {
chunks: Chunks
uploads: {[key: string]: IUploadResponse } = {}
path: string = undefined
uploadPercentage: string = "0%"
merging = false
onSetPath: Function[] = []
onSetLastChunk: Function[] = []
contentReady = 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;
}
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) {
this.uploads[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
}
}
@@ -371,15 +371,20 @@ export class ViewPublicationsPage implements OnInit {
video.pause();
})
try {
this.videoElements.forEach(videoElement => {
// You can access the native HTML video element using videoElement.nativeElement
const video: HTMLVideoElement = videoElement.nativeElement;
this.videoElements.forEach(videoElement => {
// You can access the native HTML video element using videoElement.nativeElement
const video: HTMLVideoElement = videoElement.nativeElement;
video.pause()
// Do something with each video element
// console.log(video);
});
} catch (e) {
}
video.pause()
// Do something with each video element
// console.log(video);
});
}
public onScroll(event): void {
@@ -1,14 +1,18 @@
import { Injectable } from '@angular/core';
import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service";
import { CMAPIAPIService } from "src/app/shared/API/CMAPI/cmapi-api.service";
import { ok, err } from 'neverthrow';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CMAPIService {
constructor(public MiddlewareServiceService: MiddlewareServiceService) {
window["CMAPIService"] = this
constructor(
public MiddlewareServiceService: MiddlewareServiceService,
private CMAPIAPIService: CMAPIAPIService) {
window["CMAPIAPIRepository"] = this
}
async FileContent({length, path, index, blobFile}) {
@@ -20,7 +24,33 @@ export class CMAPIService {
} catch (error) {
return err(error)
}
}
async ping() {
try {
await this.MiddlewareServiceService.tryToReachTheServer().toPromise();
return ok(true)
} catch (error) {
if(error.status == 0) {
return err(false)
}
return ok(true)
}
}
async getVideoHeader(url: string) {
try {
await this.CMAPIAPIService.getVideoHeader(url).toPromise()
return ok(true)
} catch(error) {
return err(false)
}
}
}