metube/ui/src/app/app.component.html

150 lines
5.8 KiB
HTML

<div class="app">
<app-sidebar
[status]="status"
[selectedFolder]="selectedFolder"
[statusCounts]="statusCounts"
[folders]="folderNavs"
[allCount]="allCount"
[metubeVersion]="metubeVersion"
[themes]="themes"
[activeTheme]="activeTheme"
[open]="sidebarOpen"
(statusChange)="onStatusChange($event)"
(folderChange)="onFolderChange($event)"
(openAdvanced)="toggleAdvanced(true)"
(openActivity)="activityOpen = !activityOpen"
(themeChanged)="themeChanged($event)"
(close)="sidebarOpen = false">
</app-sidebar>
<main class="main">
<app-command-bar
[url]="addUrl"
(urlChange)="addUrl = $event"
[quality]="quality"
[format]="format"
[folder]="folder"
[qualities]="qualities"
[formats]="formats"
[customDirs$]="customDirs$"
[allowCustomDir]="allowCustomDir.bind(this)"
[disabled]="addInProgress || downloads.loading"
(add)="addDownload($event)"
(qualityChange)="setQuality($event)"
(formatChange)="setFormat($event)"
(folderChange)="setFolder($event)"
(openAdvanced)="toggleAdvanced(true)"
(menu)="sidebarOpen = true">
</app-command-bar>
<app-stats-strip
[active]="activeDownloads"
[speed]="totalSpeed"
[queued]="queuedDownloads"
[storage]="librarySize">
</app-stats-strip>
<div class="content">
<app-active-downloads
[items]="downloadingRows"
[totalSpeed]="totalSpeed"
[loading]="downloads.loading"
(cancel)="cancelDownload($event)">
</app-active-downloads>
<app-download-list
[status]="status"
[rows]="filteredRows"
[folderName]="folderName"
[filterText]="filter"
(filterChange)="filter = $event"
[sort]="sort"
(sortChange)="sort = $event"
[sortAscending]="sortAscending"
(sortAscendingChange)="setSortDirection($event)"
[view]="view"
(viewChange)="setView($event)"
[loading]="downloads.loading"
[customDirsFor]="customDirsForDownload.bind(this)"
[allowCustomDir]="allowCustomDir.bind(this)"
[downloadUrlFor]="buildDownloadLink.bind(this)"
(start)="startItems($event)"
(del)="delItems($event, status === 'completed' ? 'done' : 'queue')"
(move)="moveItems($event.ids, $event.folder)"
(retry)="retryDownload($event.key, $event.dl)"
(folderEdit)="folderChanged($event.key, $event.folder)"
(clearCompleted)="clearCompletedDownloads()"
(clearFailed)="clearFailedDownloads()"
(retryFailed)="retryFailedDownloads()"
(downloadSelected)="downloadSelectedFiles($event)">
</app-download-list>
</div>
</main>
</div>
<!-- Advanced options slide-over -->
<app-advanced-options
[open]="isAdvancedOpen"
[autoStart]="autoStart"
(autoStartChange)="setAutoStart($event)"
[playlistStrictMode]="playlistStrictMode"
(strictChange)="playlistStrictMode = $event"
[playlistItemLimit]="playlistItemLimit"
(limitChange)="playlistItemLimit = $event"
[customNamePrefix]="customNamePrefix"
(prefixChange)="customNamePrefix = $event"
[metubeVersion]="metubeVersion"
[ytDlpVersion]="ytDlpVersion"
[ytDlpOptionsUpdateTime]="ytDlpOptionsUpdateTime"
(close)="toggleAdvanced(false)"
(import)="openBatchImportModal()"
(export)="exportBatchUrls('all')"
(copy)="copyBatchUrls('all')"
(cookie)="saveCookie($event.domain, $event.cookie)">
</app-advanced-options>
<!-- Batch import modal -->
<div class="modal fade" tabindex="-1" role="dialog" [ngClass]="{'show': batchImportModalOpen}" [ngStyle]="{'display': batchImportModalOpen ? 'block' : 'none'}">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">批量导入 URL</h5>
<button type="button" class="btn-close" aria-label="关闭" (click)="closeBatchImportModal()"></button>
</div>
<div class="modal-body">
<textarea [(ngModel)]="batchImportText" class="form-control" rows="6" placeholder="每行粘贴一个视频 URL"></textarea>
<div class="mt-2">
<small *ngIf="batchImportStatus" class="batch-status">{{ batchImportStatus }}</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger me-auto" *ngIf="importInProgress" (click)="cancelBatchImport()">取消导入</button>
<button type="button" class="btn btn-secondary" (click)="closeBatchImportModal()">关闭</button>
<button type="button" class="btn btn-primary" (click)="startBatchImport()" [disabled]="importInProgress">导入 URL</button>
</div>
</div>
</div>
</div>
<!-- Activity drawer -->
<div class="scrim" *ngIf="activityOpen" (click)="activityOpen = false"></div>
<aside class="activity" [class.show]="activityOpen" aria-label="活动日志">
<div class="activity-head">
<span class="activity-title">活动日志</span>
<button type="button" class="icon-btn neutral" (click)="activityOpen = false" aria-label="关闭">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
<div class="activity-body">
<div *ngIf="events.length === 0" class="activity-empty">暂无事件</div>
<div *ngFor="let event of events" class="activity-item">
<div class="activity-msg">{{ event.message }}</div>
<div class="activity-url" *ngIf="event.url" [title]="event.url">{{ event.url }}</div>
<div class="activity-time num">{{ getRelativeTime(event.timestamp) }}</div>
</div>
<button type="button" class="ghost-btn activity-clear" (click)="clearEvents()">清空日志</button>
</div>
</aside>
<app-toasts></app-toasts>