chore: update Angular TypeScript build info cache

This commit is contained in:
Bruno Charest 2025-09-15 13:58:33 -04:00
parent 2866d74b32
commit 23c9ec539e
15 changed files with 145 additions and 61 deletions

File diff suppressed because one or more lines are too long

View File

@ -100,8 +100,8 @@ import {
DOCUMENT, DOCUMENT,
IMAGE_CONFIG IMAGE_CONFIG
} from "./chunk-FVA7C6JK.js"; } from "./chunk-FVA7C6JK.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-JRFR6BLO.js"; import "./chunk-JRFR6BLO.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-MARUHEWW.js"; import "./chunk-MARUHEWW.js";
import "./chunk-GOMI4DH3.js"; import "./chunk-GOMI4DH3.js";
export { export {

View File

@ -41,8 +41,8 @@ import {
} from "./chunk-5DRVFSXL.js"; } from "./chunk-5DRVFSXL.js";
import "./chunk-OUSM42MY.js"; import "./chunk-OUSM42MY.js";
import "./chunk-FVA7C6JK.js"; import "./chunk-FVA7C6JK.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-JRFR6BLO.js"; import "./chunk-JRFR6BLO.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-MARUHEWW.js"; import "./chunk-MARUHEWW.js";
import "./chunk-GOMI4DH3.js"; import "./chunk-GOMI4DH3.js";
export { export {

View File

@ -498,8 +498,8 @@ import {
ɵɵviewQuery, ɵɵviewQuery,
ɵɵviewQuerySignal ɵɵviewQuerySignal
} from "./chunk-FVA7C6JK.js"; } from "./chunk-FVA7C6JK.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-JRFR6BLO.js"; import "./chunk-JRFR6BLO.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-MARUHEWW.js"; import "./chunk-MARUHEWW.js";
import "./chunk-GOMI4DH3.js"; import "./chunk-GOMI4DH3.js";
export { export {

View File

@ -46,10 +46,10 @@ import {
ɵɵgetInheritedFactory, ɵɵgetInheritedFactory,
ɵɵlistener ɵɵlistener
} from "./chunk-FVA7C6JK.js"; } from "./chunk-FVA7C6JK.js";
import "./chunk-JRFR6BLO.js";
import { import {
forkJoin forkJoin
} from "./chunk-HWYXSU2G.js"; } from "./chunk-HWYXSU2G.js";
import "./chunk-JRFR6BLO.js";
import { import {
Subject, Subject,
from, from,

View File

@ -41,8 +41,8 @@ import {
} from "./chunk-H4LQPAO2.js"; } from "./chunk-H4LQPAO2.js";
import "./chunk-OUSM42MY.js"; import "./chunk-OUSM42MY.js";
import "./chunk-FVA7C6JK.js"; import "./chunk-FVA7C6JK.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-JRFR6BLO.js"; import "./chunk-JRFR6BLO.js";
import "./chunk-HWYXSU2G.js";
import "./chunk-MARUHEWW.js"; import "./chunk-MARUHEWW.js";
import "./chunk-GOMI4DH3.js"; import "./chunk-GOMI4DH3.js";
export { export {

View File

@ -83,11 +83,11 @@ import {
ɵɵqueryRefresh, ɵɵqueryRefresh,
ɵɵsanitizeUrlOrResourceUrl ɵɵsanitizeUrlOrResourceUrl
} from "./chunk-FVA7C6JK.js"; } from "./chunk-FVA7C6JK.js";
import "./chunk-JRFR6BLO.js";
import { import {
defer, defer,
isObservable isObservable
} from "./chunk-HWYXSU2G.js"; } from "./chunk-HWYXSU2G.js";
import "./chunk-JRFR6BLO.js";
import { import {
BehaviorSubject, BehaviorSubject,
ConnectableObservable, ConnectableObservable,

View File

@ -1,61 +1,61 @@
{ {
"hash": "23edc511", "hash": "4a15fadf",
"configHash": "2277c002", "configHash": "d859ec53",
"lockfileHash": "c86d7ad1", "lockfileHash": "c86d7ad1",
"browserHash": "0d41a6ee", "browserHash": "3b79ea76",
"optimized": { "optimized": {
"@angular/common": { "@angular/common": {
"src": "../../../../../../node_modules/@angular/common/fesm2022/common.mjs", "src": "../../../../../../node_modules/@angular/common/fesm2022/common.mjs",
"file": "@angular_common.js", "file": "@angular_common.js",
"fileHash": "ed7bea66", "fileHash": "3cdf8c58",
"needsInterop": false "needsInterop": false
}, },
"@angular/common/http": { "@angular/common/http": {
"src": "../../../../../../node_modules/@angular/common/fesm2022/http.mjs", "src": "../../../../../../node_modules/@angular/common/fesm2022/http.mjs",
"file": "@angular_common_http.js", "file": "@angular_common_http.js",
"fileHash": "d8740647", "fileHash": "c729a905",
"needsInterop": false "needsInterop": false
}, },
"@angular/core": { "@angular/core": {
"src": "../../../../../../node_modules/@angular/core/fesm2022/core.mjs", "src": "../../../../../../node_modules/@angular/core/fesm2022/core.mjs",
"file": "@angular_core.js", "file": "@angular_core.js",
"fileHash": "fc2503ca", "fileHash": "262b482a",
"needsInterop": false "needsInterop": false
}, },
"@angular/forms": { "@angular/forms": {
"src": "../../../../../../node_modules/@angular/forms/fesm2022/forms.mjs", "src": "../../../../../../node_modules/@angular/forms/fesm2022/forms.mjs",
"file": "@angular_forms.js", "file": "@angular_forms.js",
"fileHash": "36d0134e", "fileHash": "08308e50",
"needsInterop": false "needsInterop": false
}, },
"@angular/platform-browser": { "@angular/platform-browser": {
"src": "../../../../../../node_modules/@angular/platform-browser/fesm2022/platform-browser.mjs", "src": "../../../../../../node_modules/@angular/platform-browser/fesm2022/platform-browser.mjs",
"file": "@angular_platform-browser.js", "file": "@angular_platform-browser.js",
"fileHash": "c0c2a1fa", "fileHash": "f61025b6",
"needsInterop": false "needsInterop": false
}, },
"@angular/router": { "@angular/router": {
"src": "../../../../../../node_modules/@angular/router/fesm2022/router.mjs", "src": "../../../../../../node_modules/@angular/router/fesm2022/router.mjs",
"file": "@angular_router.js", "file": "@angular_router.js",
"fileHash": "381708ba", "fileHash": "f2b90ce6",
"needsInterop": false "needsInterop": false
}, },
"@google/genai": { "@google/genai": {
"src": "../../../../../../node_modules/@google/genai/dist/web/index.mjs", "src": "../../../../../../node_modules/@google/genai/dist/web/index.mjs",
"file": "@google_genai.js", "file": "@google_genai.js",
"fileHash": "a56c743a", "fileHash": "3476d74f",
"needsInterop": false "needsInterop": false
}, },
"rxjs": { "rxjs": {
"src": "../../../../../../node_modules/rxjs/dist/esm5/index.js", "src": "../../../../../../node_modules/rxjs/dist/esm5/index.js",
"file": "rxjs.js", "file": "rxjs.js",
"fileHash": "c69b23b3", "fileHash": "df88f612",
"needsInterop": false "needsInterop": false
}, },
"rxjs/operators": { "rxjs/operators": {
"src": "../../../../../../node_modules/rxjs/dist/esm5/operators/index.js", "src": "../../../../../../node_modules/rxjs/dist/esm5/operators/index.js",
"file": "rxjs_operators.js", "file": "rxjs_operators.js",
"fileHash": "56086c3c", "fileHash": "8d5942d8",
"needsInterop": false "needsInterop": false
} }
}, },
@ -75,12 +75,12 @@
"chunk-FVA7C6JK": { "chunk-FVA7C6JK": {
"file": "chunk-FVA7C6JK.js" "file": "chunk-FVA7C6JK.js"
}, },
"chunk-HWYXSU2G": {
"file": "chunk-HWYXSU2G.js"
},
"chunk-JRFR6BLO": { "chunk-JRFR6BLO": {
"file": "chunk-JRFR6BLO.js" "file": "chunk-JRFR6BLO.js"
}, },
"chunk-HWYXSU2G": {
"file": "chunk-HWYXSU2G.js"
},
"chunk-MARUHEWW": { "chunk-MARUHEWW": {
"file": "chunk-MARUHEWW.js" "file": "chunk-MARUHEWW.js"
}, },

View File

@ -1,8 +1,8 @@
{ {
"hash": "bd8fc5b3", "hash": "65ebd7bc",
"configHash": "d5bc65c8", "configHash": "3d00a7fd",
"lockfileHash": "c86d7ad1", "lockfileHash": "c86d7ad1",
"browserHash": "5244fe32", "browserHash": "acdb5c3c",
"optimized": {}, "optimized": {},
"chunks": {} "chunks": {}
} }

Binary file not shown.

View File

@ -561,6 +561,37 @@ r.get('/peertube/:instance/*', async (req, res) => {
} }
}); });
// -------------------- Generic video details (GET) --------------------
// Returns metadata such as title, description, uploader, thumbnail, duration and views for a provider/videoId
// Supports query params similar to download endpoints: instance (PeerTube), slug (Odysee), sourceUrl (direct)
r.get('/details/:provider/:videoId', async (req, res) => {
try {
const { provider, videoId } = req.params;
const instance = req.query.instance || undefined;
const slug = req.query.slug || undefined;
const sourceUrl = req.query.sourceUrl || undefined;
const url = providerUrlFrom(provider, videoId, { instance, slug, sourceUrl });
const raw = await youtubedl(url, { dumpSingleJson: true, noWarnings: true, noCheckCertificates: true, skipDownload: true });
const meta = (typeof raw === 'string') ? JSON.parse(raw || '{}') : (raw || {});
const out = {
videoId,
title: meta.title || '',
thumbnail: meta.thumbnail || (Array.isArray(meta.thumbnails) && meta.thumbnails.length ? meta.thumbnails[0].url : ''),
uploaderName: meta.uploader || meta.channel || '',
uploaderAvatar: '',
views: typeof meta.view_count === 'number' ? meta.view_count : (typeof meta.viewCount === 'number' ? meta.viewCount : 0),
duration: typeof meta.duration === 'number' ? meta.duration : 0,
uploadedDate: meta.upload_date ? new Date(meta.upload_date.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3')).toISOString() : (meta.release_timestamp ? new Date(meta.release_timestamp * 1000).toISOString() : ''),
description: meta.description || meta.summary || '',
url,
type: 'video',
};
return res.json(out);
} catch (e) {
return res.status(500).json({ error: 'details_failed', details: String(e?.message || e) });
}
});
// Download routes middleware (auth supports both Authorization header and cookies) // Download routes middleware (auth supports both Authorization header and cookies)
r.use('/download', authMiddlewareCookieAware, downloadLimiter); r.use('/download', authMiddlewareCookieAware, downloadLimiter);

View File

@ -21,19 +21,20 @@
<span [class.hidden]="collapsed">{{ 'nav.shorts' | t }}</span> <span [class.hidden]="collapsed">{{ 'nav.shorts' | t }}</span>
</a> </a>
</li> </li>
</ul>
</div>
<!-- Vous -->
@if (isLoggedIn()) {
<div>
<div class="px-3 py-2 text-xs uppercase tracking-wide text-slate-400" [class.hidden]="collapsed">{{ 'nav.you' | t }}</div>
<ul class="space-y-1">
<li> <li>
<a routerLink="/library/subscriptions" routerLinkActive="bg-slate-800" class="flex items-center px-3 py-2 rounded hover:bg-slate-800 transition" [ngClass]="{ 'gap-0 justify-center': collapsed, 'gap-3': !collapsed }" [attr.title]="collapsed ? ('nav.subscriptions' | t) : null"> <a routerLink="/library/subscriptions" routerLinkActive="bg-slate-800" class="flex items-center px-3 py-2 rounded hover:bg-slate-800 transition" [ngClass]="{ 'gap-0 justify-center': collapsed, 'gap-3': !collapsed }" [attr.title]="collapsed ? ('nav.subscriptions' | t) : null">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm0 2v12h16V6H4zm3 3h10v2H7V9zm0 4h7v2H7v-2z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm0 2v12h16V6H4zm3 3h10v2H7V9zm0 4h7v2H7v-2z"/></svg>
<span [class.hidden]="collapsed">{{ 'nav.subscriptions' | t }}</span> <span [class.hidden]="collapsed">{{ 'nav.subscriptions' | t }}</span>
</a> </a>
</li> </li>
</ul>
</div>
<!-- Vous -->
<div>
<div class="px-3 py-2 text-xs uppercase tracking-wide text-slate-400" [class.hidden]="collapsed">{{ 'nav.you' | t }}</div>
<ul class="space-y-1">
<li> <li>
<a routerLink="/account/history" routerLinkActive="bg-slate-800" class="flex items-center px-3 py-2 rounded hover:bg-slate-800 transition" [ngClass]="{ 'gap-0 justify-center': collapsed, 'gap-3': !collapsed }" [attr.title]="collapsed ? ('nav.history' | t) : null"> <a routerLink="/account/history" routerLinkActive="bg-slate-800" class="flex items-center px-3 py-2 rounded hover:bg-slate-800 transition" [ngClass]="{ 'gap-0 justify-center': collapsed, 'gap-3': !collapsed }" [attr.title]="collapsed ? ('nav.history' | t) : null">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M12 8a1 1 0 0 1 1 1v3.38l2.32 1.34a1 1 0 1 1-1 1.74l-2.82-1.63A1 1 0 0 1 11 13V9a1 1 0 0 1 1-1zm0-6a10 10 0 1 0 10 10 10.011 10.011 0 0 0-10-10z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M12 8a1 1 0 0 1 1 1v3.38l2.32 1.34a1 1 0 1 1-1 1.74l-2.82-1.63A1 1 0 0 1 11 13V9a1 1 0 0 1 1-1zm0-6a10 10 0 1 0 10 10 10.011 10.011 0 0 0-10-10z"/></svg>
@ -54,6 +55,7 @@
</li> </li>
</ul> </ul>
</div> </div>
}
<!-- Fournisseurs --> <!-- Fournisseurs -->
<div> <div>

View File

@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common';
import { RouterLink, RouterLinkActive } from '@angular/router'; import { RouterLink, RouterLinkActive } from '@angular/router';
import { InstanceService } from '../../services/instance.service'; import { InstanceService } from '../../services/instance.service';
import { ThemesService } from '../../services/themes.service'; import { ThemesService } from '../../services/themes.service';
import { AuthService } from '../../services/auth.service';
import { TranslatePipe } from '../../pipes/translate.pipe'; import { TranslatePipe } from '../../pipes/translate.pipe';
@Component({ @Component({
@ -14,8 +15,12 @@ import { TranslatePipe } from '../../pipes/translate.pipe';
}) })
export class SidebarComponent { export class SidebarComponent {
private instances = inject(InstanceService); private instances = inject(InstanceService);
private auth = inject(AuthService);
themes = inject(ThemesService); themes = inject(ThemesService);
// Check if user is logged in
isLoggedIn = computed(() => !!this.auth.currentUser());
provider = computed(() => this.instances.selectedProvider()); provider = computed(() => this.instances.selectedProvider());
providerLabel = computed(() => this.instances.selectedProviderLabel()); providerLabel = computed(() => this.instances.selectedProviderLabel());
// Providers with PeerTube last // Providers with PeerTube last

View File

@ -100,10 +100,14 @@
</div> </div>
<div class="mt-4 bg-slate-800/70 p-4 rounded-lg"> <div class="mt-4 bg-slate-800/70 p-4 rounded-lg">
<p [class.line-clamp-3]="!showFullDescription()">{{ v.description }}</p> <p class="whitespace-pre-wrap text-slate-300" [class.line-clamp-3]="!showFullDescription()">
{{ hasDescription() ? descriptionText() : 'Aucune description disponible.' }}
</p>
@if (showMoreAvailable()) {
<button (click)="toggleDescription()" class="text-red-400 hover:text-red-300 font-semibold mt-2"> <button (click)="toggleDescription()" class="text-red-400 hover:text-red-300 font-semibold mt-2">
{{ showFullDescription() ? 'Show less' : 'Show more' }} {{ showFullDescription() ? 'Show less' : 'Show more' }}
</button> </button>
}
</div> </div>
<!-- Download Panel (shown only when logged in) --> <!-- Download Panel (shown only when logged in) -->

View File

@ -33,9 +33,30 @@ export class WatchComponent implements OnDestroy {
private http = inject(HttpClient); private http = inject(HttpClient);
private routeSubscription: Subscription; private routeSubscription: Subscription;
// Choose correct API base: use dev proxy when UI runs on a different port than the backend
private apiBase(): string {
try {
const port = window?.location?.port || '';
// If not running on backend port, route through Angular proxy
return port && port !== '4000' ? '/proxy/api' : '/api';
} catch {
return '/api';
}
}
video = signal<VideoDetail | null>(null); video = signal<VideoDetail | null>(null);
loading = signal(true); loading = signal(true);
showFullDescription = signal(false); showFullDescription = signal(false);
// Prefer full description if available; otherwise fallback to shortDescription
descriptionText = computed(() => {
const v = this.video();
const full = (v?.description || '').trim();
if (full) return full;
const short = (v?.shortDescription || '').trim();
return short || '';
});
hasDescription = computed(() => this.descriptionText().length > 0);
showMoreAvailable = computed(() => this.descriptionText().length > 240);
summary = signal<string | null>(null); summary = signal<string | null>(null);
isSummarizing = signal(false); isSummarizing = signal(false);
@ -268,9 +289,30 @@ export class WatchComponent implements OnDestroy {
} }
}); });
} else { } else {
// For other providers rely on embed/placeholder // For other providers, enrich details via backend using yt-dlp metadata when possible
const opts = this.buildProviderOpts();
this.http.get<any>(`${this.apiBase()}/details/${encodeURIComponent(provider)}/${encodeURIComponent(id)}`, { params: opts as any }).subscribe({
next: (data) => {
this.video.update(v => v ? {
...v,
title: data?.title || v.title,
thumbnail: data?.thumbnail || v.thumbnail,
uploaderName: data?.uploaderName || v.uploaderName,
uploadedDate: data?.uploadedDate || v.uploadedDate,
views: typeof data?.views === 'number' ? data.views : v.views,
duration: typeof data?.duration === 'number' ? data.duration : v.duration,
description: (data?.description || v.description || v.shortDescription || ''),
url: data?.url || v.url,
} : v);
this.loading.set(false); this.loading.set(false);
this.loadRelatedSuggestions(); this.loadRelatedSuggestions();
},
error: () => {
// Fallback to existing placeholder
this.loading.set(false);
this.loadRelatedSuggestions();
}
});
} }
// Record watch start // Record watch start