227 lines
18 KiB
HTML
227 lines
18 KiB
HTML
<nav tabindex="0" class="sidebar-scroll h-full w-full bg-slate-900 md:bg-transparent text-slate-200 p-3 md:p-0">
|
|
<div class="space-y-6">
|
|
<!-- Brand (small only) -->
|
|
<div class="md:hidden flex items-center gap-2 px-3 py-2">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-red-500" viewBox="0 0 24 24" fill="currentColor"><path d="M10,15.6l5.3-3.3L10,9V15.6z M21.8,8.1c-0.2-0.8-0.9-1.4-1.7-1.7C18.2,6,12,6,12,6s-6.2,0-8.1,0.5 c-0.8,0.2-1.4,0.9-1.7,1.7C2,9.9,2,12,2,12s0,2.1,0.5,3.9c0.2,0.8,0.9,1.4,1.7,1.7C6.2,18,12,18,12,18s6.2,0,8.1-0.5 c0.8-0.2,1.4-0.9,1.7-1.7c0.5-1.8,0.5-3.9,0.5-3.9S22.2,9.9,21.8,8.1z"/></svg>
|
|
<span class="text-xl font-bold">NewTube</span>
|
|
</div>
|
|
|
|
<!-- Main : toujours visible, hors accordeon -->
|
|
<div>
|
|
<ul class="space-y-1">
|
|
<li>
|
|
<a routerLink="/t/trending" 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.home' | t) : null">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M3 10.5L12 3l9 7.5V21a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1v-10.5z"/></svg>
|
|
<span [class.hidden]="collapsed">{{ 'nav.home' | t }}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a routerLink="/shorts" 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.shorts' | t) : null">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M10 2l8 4v9l-8 4-8-4V6l8-4zm0 2.2L4 6.8v6.4l6 2.6 6-2.6V6.8l-6-2.6z"/></svg>
|
|
<span [class.hidden]="collapsed">{{ 'nav.shorts' | t }}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a routerLink="/library/playlists" 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.playlists' | 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 6h12v2H4V6zm0 4h12v2H4v-2zm0 4h8v2H4v-2zm14-6h2v8h-2v-8z"/></svg>
|
|
<span [class.hidden]="collapsed">{{ 'nav.playlists' | t }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Vous -->
|
|
@if (isLoggedIn()) {
|
|
<div>
|
|
<button type="button" (click)="toggleSection('you')" [attr.aria-expanded]="isOpen('you')" aria-controls="sidebar-section-you" class="flex w-full items-center justify-between px-3 py-2 text-xs uppercase tracking-wide text-slate-400 hover:text-slate-200 transition" [class.hidden]="collapsed">
|
|
<span>{{ 'nav.you' | t }}</span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 transition-transform" [class.rotate-180]="isOpen('you')" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M7 10l5 5 5-5z"/></svg>
|
|
</button>
|
|
<div id="sidebar-section-you" [hidden]="!collapsed && !isOpen('you')">
|
|
<ul class="space-y-1">
|
|
<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">
|
|
<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>
|
|
</a>
|
|
</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">
|
|
<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>
|
|
<span [class.hidden]="collapsed">{{ 'nav.history' | t }}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a routerLink="/library/liked" 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.liked' | 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 21s-6.716-4.248-9.193-6.725A6 6 0 0 1 12 5.414 6 6 0 0 1 21.193 14.275C18.716 16.752 12 21 12 21z"/></svg>
|
|
<span [class.hidden]="collapsed">{{ 'nav.liked' | t }}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a routerLink="/library/downloads" 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.downloads' | 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 3v10.17l3.59-3.58L17 11l-5 5-5-5 1.41-1.41L12 13.17V3h0zm-7 15h14v2H5v-2z"/></svg>
|
|
<span [class.hidden]="collapsed">{{ 'nav.downloads' | t }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Groupes d'abonnements (façon PocketTube) -->
|
|
<div *ngIf="!collapsed && subscriptionGroups().length > 0">
|
|
<button type="button" (click)="toggleSection('groups')" [attr.aria-expanded]="isOpen('groups')" aria-controls="sidebar-section-groups" class="flex w-full items-center justify-between px-3 py-2 text-xs uppercase tracking-wide text-slate-400 hover:text-slate-200 transition">
|
|
<span>{{ 'nav.groups' | t }} <span class="text-slate-500">({{ subscriptionGroups().length }})</span></span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 transition-transform" [class.rotate-180]="isOpen('groups')" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M7 10l5 5 5-5z"/></svg>
|
|
</button>
|
|
<div id="sidebar-section-groups" [hidden]="!isOpen('groups')">
|
|
<ul class="space-y-1">
|
|
<li *ngFor="let group of displayedGroups()">
|
|
<a [routerLink]="['/library/subscriptions']" [queryParams]="{ group: group.id, tab: 'channels' }" routerLinkActive="bg-slate-800" class="flex items-center px-3 py-2 rounded hover:bg-slate-800 transition gap-3">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded text-base" [style.background-color]="group.color + '26'">{{ group.icon }}</span>
|
|
<span class="flex-1 truncate text-sm">{{ group.name }}</span>
|
|
<span class="text-xs text-slate-500">{{ group.channelCount }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<button *ngIf="subscriptionGroups().length > 5" type="button" class="flex items-center gap-2 px-3 py-2 text-sm text-slate-300 hover:text-white" (click)="toggleGroups()">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 transition-transform" [class.rotate-180]="showAllGroups()" viewBox="0 0 24 24" fill="currentColor"><path d="M7 10l5 5 5-5z"/></svg>
|
|
<span>{{ showAllGroups() ? ('common.less' | t) : ('common.more' | t) }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- Fournisseurs -->
|
|
<div>
|
|
<button type="button" (click)="toggleSection('providers')" [attr.aria-expanded]="isOpen('providers')" aria-controls="sidebar-section-providers" class="flex w-full items-center justify-between px-3 py-2 text-xs uppercase tracking-wide text-slate-400 hover:text-slate-200 transition" [class.hidden]="collapsed">
|
|
<span>{{ 'nav.providers' | t }} <span class="text-slate-500">({{ providersList().length }})</span></span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 transition-transform" [class.rotate-180]="isOpen('providers')" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M7 10l5 5 5-5z"/></svg>
|
|
</button>
|
|
<div id="sidebar-section-providers" [hidden]="!collapsed && !isOpen('providers')">
|
|
<ul class="space-y-1">
|
|
<!-- All providers except PeerTube (order handled in TS so PT is last) -->
|
|
<ng-container *ngFor="let p of providersList()">
|
|
<li *ngIf="p.id !== 'peertube'">
|
|
<a [routerLink]="['/p', p.id, 't', 'trending']" 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 ? (p.label) : null">
|
|
<span class="h-6 w-6 flex items-center justify-center">
|
|
<ng-container [ngSwitch]="p.id">
|
|
<!-- YouTube -->
|
|
<svg *ngSwitchCase="'youtube'" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
<rect x="3" y="6" width="18" height="12" rx="3" class="text-red-600" fill="currentColor"/>
|
|
<polygon points="10,9 16,12 10,15" fill="white"/>
|
|
</svg>
|
|
<!-- Dailymotion -->
|
|
<svg *ngSwitchCase="'dailymotion'" class="h-5 w-5 text-blue-500" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor"/>
|
|
<polygon points="11,8 16,12 11,16" fill="white"/>
|
|
</svg>
|
|
<!-- Twitch -->
|
|
<svg *ngSwitchCase="'twitch'" class="h-5 w-5 text-purple-500" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
<path d="M4 3h16v11l-4 4h-3l-2 2H9v-2H6V3zm3 2v9h6l2-2h3V5H7z" fill="currentColor"/>
|
|
</svg>
|
|
<!-- Rumble -->
|
|
<svg *ngSwitchCase="'rumble'" class="h-5 w-5 text-green-500" viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor"/>
|
|
<polygon points="10,8 16,12 10,16" fill="white"/>
|
|
</svg>
|
|
<!-- Odysee -->
|
|
<svg *ngSwitchCase="'odysee'" class="h-5 w-5 text-pink-500" viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor"/>
|
|
<circle cx="12" cy="12" r="5" fill="white"/>
|
|
</svg>
|
|
<!-- Fallback generic play icon -->
|
|
<svg *ngSwitchDefault class="h-5 w-5 text-slate-300" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
<polygon points="9,7 17,12 9,17" fill="currentColor"/>
|
|
</svg>
|
|
</ng-container>
|
|
</span>
|
|
<span [class.hidden]="collapsed">{{ p.label }}</span>
|
|
</a>
|
|
</li>
|
|
</ng-container>
|
|
|
|
<!-- PeerTube group with instances as sub-items -->
|
|
<ng-container *ngFor="let p of providersList()">
|
|
<li [ngClass]="{ 'mt-2': true }" *ngIf="p.id === 'peertube'">
|
|
<a [routerLink]="['/p', 'peertube', 't', 'trending']" 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 ? (p.label) : null">
|
|
<span class="h-6 w-6 flex items-center justify-center">
|
|
<!-- PeerTube logo style (orange play) -->
|
|
<svg class="h-5 w-5 text-orange-500" viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor"/>
|
|
<polygon points="10,8 16,12 10,16" fill="white"/>
|
|
</svg>
|
|
</span>
|
|
<span [class.hidden]="collapsed">{{ p.label }}</span>
|
|
</a>
|
|
<!-- Sub-list of instances (visible when not collapsed) -->
|
|
<ul class="ml-8 mt-1 space-y-1" [class.hidden]="collapsed">
|
|
<li *ngFor="let inst of displayedInstances()">
|
|
<a [routerLink]="['/p', 'peertube', 't', 'trending']"
|
|
(click)="$event.preventDefault(); selectPeerTubeInstance(inst)"
|
|
class="flex items-center px-3 py-1.5 rounded hover:bg-slate-800 transition gap-2">
|
|
<svg class="h-4 w-4 text-orange-500" viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor"/>
|
|
<polygon points="10,8 16,12 10,16" fill="white"/>
|
|
</svg>
|
|
<span class="text-xs" [ngClass]="{ 'text-sky-400': inst === activePeerTubeInstance(), 'text-slate-300': inst !== activePeerTubeInstance() }">{{ inst }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<button *ngIf="!collapsed && peerTubeInstances().length > 3" type="button" class="ml-8 flex items-center gap-2 px-3 py-2 text-sm text-slate-300 hover:text-white" (click)="toggleInstances()">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 transition-transform" [class.rotate-180]="showAllInstances()" viewBox="0 0 24 24" fill="currentColor"><path d="M7 10l5 5 5-5z"/></svg>
|
|
<span>{{ showAllInstances() ? ('common.less' | t) : ('common.more' | t) }}</span>
|
|
</button>
|
|
</li>
|
|
</ng-container>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Explorer (themes list with more/less) -->
|
|
<div>
|
|
<button type="button" (click)="toggleSection('explore')" [attr.aria-expanded]="isOpen('explore')" aria-controls="sidebar-section-explore" class="flex w-full items-center justify-between px-3 py-2 text-xs uppercase tracking-wide text-slate-400 hover:text-slate-200 transition" [class.hidden]="collapsed">
|
|
<span>{{ 'nav.explore' | t }} <span class="text-slate-500">({{ themes.themes().length }})</span></span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 transition-transform" [class.rotate-180]="isOpen('explore')" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M7 10l5 5 5-5z"/></svg>
|
|
</button>
|
|
<div id="sidebar-section-explore" [hidden]="!collapsed && !isOpen('explore')">
|
|
<ul class="space-y-1">
|
|
<li *ngFor="let t of displayedThemes()">
|
|
<a [routerLink]="['/t', t.slug]" 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 ? (t.label) : null">
|
|
<span class="h-6 w-6 flex items-center justify-center text-lg">{{ t.emoji }}</span>
|
|
<span [class.hidden]="collapsed">{{ t.label }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<button type="button" class="flex items-center gap-2 px-3 py-2 text-sm text-slate-300 hover:text-white" (click)="toggleThemes()" [class.hidden]="collapsed">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 transition-transform" [class.rotate-180]="showAllThemes()" viewBox="0 0 24 24" fill="currentColor"><path d="M7 10l5 5 5-5z"/></svg>
|
|
<span>{{ showAllThemes() ? ('common.less' | t) : ('common.more' | t) }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Informations -->
|
|
<div>
|
|
<button type="button" (click)="toggleSection('info')" [attr.aria-expanded]="isOpen('info')" aria-controls="sidebar-section-info" class="flex w-full items-center justify-between px-3 py-2 text-xs uppercase tracking-wide text-slate-400 hover:text-slate-200 transition" [class.hidden]="collapsed">
|
|
<span>{{ 'nav.info' | t }}</span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 transition-transform" [class.rotate-180]="isOpen('info')" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M7 10l5 5 5-5z"/></svg>
|
|
</button>
|
|
<div id="sidebar-section-info" [hidden]="!collapsed && !isOpen('info')">
|
|
<ul class="space-y-1">
|
|
<li>
|
|
<a routerLink="/info/utilisation" 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.usage' | 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 2a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2zm1 15h-2v-6h2zm0-8h-2V7h2z"/></svg>
|
|
<span [class.hidden]="collapsed">{{ 'nav.usage' | t }}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://git.dracodev.net/Projets/NewTube" target="_blank" rel="noopener noreferrer" 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 ? 'Gitea' : null">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2zm1 14.59V20h-2v-3.41a4.994 4.994 0 0 1-4-4.9V7h2v4.69A3 3 0 0 0 12 14a3 3 0 0 0 3-2.31V7h2v4.69a4.994 4.994 0 0 1-4 4.9z"/></svg>
|
|
<span [class.hidden]="collapsed">Gitea</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|