diff --git a/package-lock.json b/package-lock.json index 9c0fda4..ef35a71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,8 +33,7 @@ "nan": "^2.14.1", "ngx-avatars": "1.4.1", "ngx-file-drop": "^15.0.0", - "rxjs": "^6.6.3", - "rxjs-compat": "^6.6.7", + "rxjs": "^7.8.2", "tslib": "^2.0.0", "typescript": "~5.9.3", "xliff-to-json": "^1.0.4", @@ -311,16 +310,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/architect/node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@angular-devkit/build-angular": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-21.1.5.tgz", @@ -741,16 +730,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -813,16 +792,6 @@ "webpack-dev-server": "^5.0.2" } }, - "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@angular-devkit/core": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.1.5.tgz", @@ -879,15 +848,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@angular-devkit/schematics": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.1.5.tgz", @@ -907,16 +867,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@angular/animations": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.1.5.tgz", @@ -14547,29 +14497,14 @@ } }, "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" + "tslib": "^2.1.0" } }, - "node_modules/rxjs-compat": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs-compat/-/rxjs-compat-6.6.7.tgz", - "integrity": "sha512-szN4fK+TqBPOFBcBcsR0g2cmTTUF/vaFEOZNuSdfU8/pGFnNmmn2u8SystYXG1QMrjOPBc6XTKHMVfENDf6hHw==", - "license": "Apache-2.0" - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", diff --git a/package.json b/package.json index 1930769..180d777 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,7 @@ "nan": "^2.14.1", "ngx-avatars": "1.4.1", "ngx-file-drop": "^15.0.0", - "rxjs": "^6.6.3", - "rxjs-compat": "^6.6.7", + "rxjs": "^7.8.2", "tslib": "^2.0.0", "typescript": "~5.9.3", "xliff-to-json": "^1.0.4", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 4c45140..73aa083 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -5,14 +5,6 @@ import { MatDialog } from '@angular/material/dialog'; import { MatSidenav } from '@angular/material/sidenav'; import { MatSnackBar } from '@angular/material/snack-bar'; import { saveAs } from 'file-saver'; -import 'rxjs/add/observable/of'; -import 'rxjs/add/operator/mapTo'; -import 'rxjs/add/operator/toPromise'; -import 'rxjs/add/observable/fromEvent' -import 'rxjs/add/operator/filter' -import 'rxjs/add/operator/debounceTime' -import 'rxjs/add/operator/do' -import 'rxjs/add/operator/switch' import { Router, NavigationStart, NavigationEnd } from '@angular/router'; import { OverlayContainer } from '@angular/cdk/overlay'; import { THEMES_CONFIG } from '../themes'; @@ -228,4 +220,3 @@ export class AppComponent implements OnInit, AfterViewInit { } } - diff --git a/src/app/components/recent-videos/recent-videos.component.ts b/src/app/components/recent-videos/recent-videos.component.ts index 0dd3ed9..f1ec7ed 100644 --- a/src/app/components/recent-videos/recent-videos.component.ts +++ b/src/app/components/recent-videos/recent-videos.component.ts @@ -4,7 +4,7 @@ import { Router } from '@angular/router'; import { DatabaseFile, FileType, FileTypeFilter, Sort } from '../../../api-types'; import { MatPaginator } from '@angular/material/paginator'; import { Subject } from 'rxjs'; -import { distinctUntilChanged, filter, take } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, filter, take } from 'rxjs/operators'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { MatChipListboxChange } from '@angular/material/chips'; import { MatSelectionListChange } from '@angular/material/list'; @@ -141,8 +141,9 @@ export class RecentVideosComponent implements OnInit { this.selected_data_objs = this.defaultSelected; this.searchChangedSubject - .debounceTime(500) - .pipe(distinctUntilChanged() + .pipe( + debounceTime(500), + distinctUntilChanged() ).subscribe(model => { if (model.length > 0) { this.search_mode = true; diff --git a/src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.ts b/src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.ts index 3a9544a..e752363 100644 --- a/src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.ts +++ b/src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.ts @@ -5,8 +5,7 @@ import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { UntypedFormControl } from '@angular/forms'; import { args, ArgsByCategory, args_info } from './youtubedl_args'; import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators/map'; -import { startWith } from 'rxjs/operators/startWith'; +import { map, startWith } from 'rxjs/operators'; import { MatAutocompleteTrigger } from '@angular/material/autocomplete'; @Pipe({ diff --git a/src/app/http.interceptor.ts b/src/app/http.interceptor.ts index 0e755cc..88b086c 100644 --- a/src/app/http.interceptor.ts +++ b/src/app/http.interceptor.ts @@ -1,38 +1,15 @@ import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http'; -import { ApplicationRef, inject } from '@angular/core'; +import { inject } from '@angular/core'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { throwError } from 'rxjs'; -import { catchError, tap } from 'rxjs/operators'; - -let tickQueued = false; - -function scheduleUiTick(appRef: ApplicationRef): void { - if (tickQueued) { - return; - } - tickQueued = true; - setTimeout(() => { - tickQueued = false; - try { - appRef.tick(); - } catch { - // Ignore if Angular is mid-navigation or being destroyed. - } - }); -} +import { catchError } from 'rxjs/operators'; export const h401InterceptorFn: HttpInterceptorFn = (request, next) => { const router = inject(Router); const snackBar = inject(MatSnackBar); - const appRef = inject(ApplicationRef); return next(request).pipe( - tap({ - next: () => scheduleUiTick(appRef), - error: () => scheduleUiTick(appRef), - complete: () => scheduleUiTick(appRef) - }), catchError((err: HttpErrorResponse) => { if (err.status === 401) { localStorage.setItem('jwt_token', null); diff --git a/src/app/main/main.component.ts b/src/app/main/main.component.ts index 7920d6e..b383c1f 100644 --- a/src/app/main/main.component.ts +++ b/src/app/main/main.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit, ElementRef, ViewChild, ViewChildren, QueryList } from '@angular/core'; import {PostsService} from '../posts.services'; -import { Observable, Subject } from 'rxjs'; +import { fromEvent, Subject } from 'rxjs'; import {UntypedFormControl, Validators} from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -11,7 +11,7 @@ import { Platform } from '@angular/cdk/platform'; import { ArgModifierDialogComponent } from 'app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component'; import { RecentVideosComponent } from 'app/components/recent-videos/recent-videos.component'; import { DatabaseFile, Download, FileType, Playlist } from 'api-types'; -import { filter, take } from 'rxjs/operators'; +import { debounceTime, filter, map, switchMap, take, tap } from 'rxjs/operators'; @Component({ selector: 'app-root', @@ -284,7 +284,7 @@ export class MainComponent implements OnInit { } this.argsChangedSubject - .debounceTime(500) + .pipe(debounceTime(500)) .subscribe((should_simulate) => { if (should_simulate) this.getSimulatedOutput(); }); @@ -694,13 +694,14 @@ export class MainComponent implements OnInit { } attachToInput(): void { - Observable.fromEvent(this.urlInput.nativeElement, 'keyup') - .map((e: any) => e.target.value) // extract the value of input - .filter((text: string) => text.length > 1) // filter out if empty - .debounceTime(250) // only once every 250ms - .do(() => this.results_loading = true) // enable loading - .map((query: string) => this.youtubeSearch.search(query)) - .switch() // act on the return of the search + fromEvent(this.urlInput.nativeElement, 'keyup') + .pipe( + map((e: any) => e.target.value), // extract the value of input + filter((text: string) => text.length > 1), // filter out if empty + debounceTime(250), // only once every 250ms + tap(() => this.results_loading = true), // enable loading + switchMap((query: string) => this.youtubeSearch.search(query)) + ) .subscribe( (results: Result[]) => { this.results_loading = false; diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts index 6495223..ec06639 100644 --- a/src/app/posts.services.ts +++ b/src/app/posts.services.ts @@ -1,8 +1,5 @@ -import {Injectable, isDevMode, Inject, DOCUMENT, NgZone} from '@angular/core'; +import {Injectable, isDevMode, Inject, DOCUMENT} from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/catch'; -import 'rxjs/add/observable/throw'; import { THEMES_CONFIG } from '../themes'; import { Router, ActivatedRouteSnapshot } from '@angular/router'; @@ -171,9 +168,8 @@ export class PostsService { version_info = null; constructor(private http: HttpClient, private router: Router, @Inject(DOCUMENT) private document: Document, - public snackBar: MatSnackBar, private titleService: Title, private ngZone: NgZone) { + public snackBar: MatSnackBar, private titleService: Title) { console.log('PostsService Initialized...'); - this.patchHttpClientIntoAngularZone(); this.path = this.document.location.origin + '/api/'; if (isDevMode()) { @@ -238,37 +234,6 @@ export class PostsService { } } - - private patchHttpClientIntoAngularZone(): void { - const httpAny = this.http as any; - if (httpAny.__ydm_zone_patched_request) { - return; - } - - const originalRequest = this.http.request.bind(this.http); - const zone = this.ngZone; - - httpAny.request = function (...args: any[]) { - const source$ = originalRequest(...args); - return new Observable(observer => { - const sub = source$.subscribe({ - next(value) { - zone.run(() => observer.next(value)); - }, - error(err) { - zone.run(() => observer.error(err)); - }, - complete() { - zone.run(() => observer.complete()); - } - }); - - return () => sub.unsubscribe(); - }); - }; - - httpAny.__ydm_zone_patched_request = true; - } canActivate(route: ActivatedRouteSnapshot, state): Promise { if (this.initialized) { return this._canActivate(route); diff --git a/src/app/youtube-search.service.ts b/src/app/youtube-search.service.ts index 2df835b..d92aade 100644 --- a/src/app/youtube-search.service.ts +++ b/src/app/youtube-search.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; export class Result { id: string @@ -49,7 +50,7 @@ export class YoutubeSearchService { `maxResults=5` ].join('&') const queryUrl = `${this.url}?${params}` - return this.http.get(queryUrl).map(response => { + return this.http.get(queryUrl).pipe(map(response => { return response['items'].map(item => { return new Result({ id: item.id.videoId, @@ -59,7 +60,7 @@ export class YoutubeSearchService { uploaded: item.snippet.publishedAt }) }) - }) + })) } // checks if url is a valid URL diff --git a/src/main.ts b/src/main.ts index 3617189..cabf9e8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,21 +20,21 @@ if (locale && locale !== 'en') { loadTranslations(data as any); import('./app/app.module').then(module => { platformBrowserDynamic() - .bootstrapModule(module.AppModule) + .bootstrapModule(module.AppModule, { ngZone: 'zone.js' }) .catch(err => console.error(err)); }); } ).catch(err => { import('./app/app.module').then(module => { platformBrowserDynamic() - .bootstrapModule(module.AppModule) + .bootstrapModule(module.AppModule, { ngZone: 'zone.js' }) .catch(err2 => console.error(err2)); }); }); } else { import('./app/app.module').then(module => { platformBrowserDynamic() - .bootstrapModule(module.AppModule) + .bootstrapModule(module.AppModule, { ngZone: 'zone.js' }) .catch(err => console.error(err)); }); } diff --git a/src/polyfills.ts b/src/polyfills.ts index 8801bb3..85b03e5 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -28,7 +28,6 @@ import '@angular/localize/init'; * Zone JS is required by Angular itself. */ import 'zone.js'; // Included with Angular CLI. -import 'zone.js/plugins/zone-patch-rxjs';