add metube version. closes #83

This commit is contained in:
Alex Shnitman 2025-06-05 20:47:49 +03:00
parent f494c4f6be
commit d74e8df408
8 changed files with 106 additions and 6 deletions

View File

@ -42,6 +42,8 @@ jobs:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
build-args: |
VERSION=${{ steps.date.outputs.date }}
tags: | tags: |
${{ secrets.DOCKERHUB_REPOSITORY }}:latest ${{ secrets.DOCKERHUB_REPOSITORY }}:latest
${{ secrets.DOCKERHUB_REPOSITORY }}:${{ steps.date.outputs.date }} ${{ secrets.DOCKERHUB_REPOSITORY }}:${{ steps.date.outputs.date }}

View File

@ -37,4 +37,9 @@ ENV STATE_DIR /downloads/.metube
ENV TEMP_DIR /downloads ENV TEMP_DIR /downloads
VOLUME /downloads VOLUME /downloads
EXPOSE 8081 EXPOSE 8081
# Add build-time argument for version
ARG VERSION=dev
ENV METUBE_VERSION=$VERSION
ENTRYPOINT ["/sbin/tini", "-g", "--", "./docker-entrypoint.sh"] ENTRYPOINT ["/sbin/tini", "-g", "--", "./docker-entrypoint.sh"]

View File

@ -258,7 +258,10 @@ def robots(request):
@routes.get(config.URL_PREFIX + 'version') @routes.get(config.URL_PREFIX + 'version')
def version(request): def version(request):
return web.json_response({"version": yt_dlp_version}) return web.json_response({
"yt-dlp": yt_dlp_version,
"version": os.getenv("METUBE_VERSION", "dev")
})
if config.URL_PREFIX != '/': if config.URL_PREFIX != '/':
@routes.get('/') @routes.get('/')

13
ui/package-lock.json generated
View File

@ -20,6 +20,7 @@
"@angular/service-worker": "^19.2.14", "@angular/service-worker": "^19.2.14",
"@fortawesome/angular-fontawesome": "~1.0.0", "@fortawesome/angular-fontawesome": "~1.0.0",
"@fortawesome/fontawesome-svg-core": "^6.7.0", "@fortawesome/fontawesome-svg-core": "^6.7.0",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/free-regular-svg-icons": "^6.7.0", "@fortawesome/free-regular-svg-icons": "^6.7.0",
"@fortawesome/free-solid-svg-icons": "^6.7.0", "@fortawesome/free-solid-svg-icons": "^6.7.0",
"@ng-bootstrap/ng-bootstrap": "^18.0.0", "@ng-bootstrap/ng-bootstrap": "^18.0.0",
@ -2986,6 +2987,18 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/@fortawesome/free-brands-svg-icons": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
"integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.7.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-regular-svg-icons": { "node_modules/@fortawesome/free-regular-svg-icons": {
"version": "6.7.2", "version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz",

View File

@ -23,6 +23,7 @@
"@angular/service-worker": "^19.2.14", "@angular/service-worker": "^19.2.14",
"@fortawesome/angular-fontawesome": "~1.0.0", "@fortawesome/angular-fontawesome": "~1.0.0",
"@fortawesome/fontawesome-svg-core": "^6.7.0", "@fortawesome/fontawesome-svg-core": "^6.7.0",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/free-regular-svg-icons": "^6.7.0", "@fortawesome/free-regular-svg-icons": "^6.7.0",
"@fortawesome/free-solid-svg-icons": "^6.7.0", "@fortawesome/free-solid-svg-icons": "^6.7.0",
"@ng-bootstrap/ng-bootstrap": "^18.0.0", "@ng-bootstrap/ng-bootstrap": "^18.0.0",

View File

@ -355,6 +355,21 @@
<footer class="footer navbar-dark bg-dark py-3 mt-5"> <footer class="footer navbar-dark bg-dark py-3 mt-5">
<div class="container text-center"> <div class="container text-center">
<small class="text-light" *ngIf="versionInfo">{{ versionInfo }}</small> <div class="footer-content" *ngIf="ytDlpVersion && metubeVersion">
<div class="version-item">
<span class="version-label">yt-dlp</span>
<span class="version-value">{{ytDlpVersion}}</span>
</div>
<div class="version-separator"></div>
<div class="version-item">
<span class="version-label">MeTube</span>
<span class="version-value">{{metubeVersion}}</span>
</div>
<div class="version-separator"></div>
<a href="https://github.com/alexta69/metube" target="_blank" class="github-link">
<fa-icon [icon]="faGithub"></fa-icon>
<span>GitHub</span>
</a>
</div>
</div> </div>
</footer> </footer>

View File

@ -126,3 +126,59 @@ td
white-space: nowrap white-space: nowrap
overflow: visible overflow: visible
text-overflow: ellipsis text-overflow: ellipsis
.footer
width: 100%
padding: 10px 0
background: linear-gradient(to bottom, rgba(0,0,0,0.2), rgba(0,0,0,0.1))
.footer-content
display: flex
justify-content: center
align-items: center
gap: 20px
color: #fff
font-size: 0.9rem
.version-item
display: flex
align-items: center
gap: 8px
.version-label
font-size: 0.75rem
text-transform: uppercase
letter-spacing: 0.5px
opacity: 0.7
.version-value
font-family: monospace
font-size: 0.85rem
padding: 2px 6px
background: rgba(255,255,255,0.1)
border-radius: 4px
.version-separator
width: 1px
height: 16px
background: rgba(255,255,255,0.2)
margin: 0 4px
.github-link
display: flex
align-items: center
gap: 6px
color: #fff
text-decoration: none
font-size: 0.85rem
padding: 2px 8px
border-radius: 4px
transition: background-color 0.2s ease
&:hover
background: rgba(255,255,255,0.1)
color: #fff
text-decoration: none
i
font-size: 1rem

View File

@ -2,6 +2,7 @@ import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { faTrashAlt, faCheckCircle, faTimesCircle, IconDefinition } from '@fortawesome/free-regular-svg-icons'; import { faTrashAlt, faCheckCircle, faTimesCircle, IconDefinition } from '@fortawesome/free-regular-svg-icons';
import { faRedoAlt, faSun, faMoon, faCircleHalfStroke, faCheck, faExternalLinkAlt, faDownload, faFileImport, faFileExport, faCopy } from '@fortawesome/free-solid-svg-icons'; import { faRedoAlt, faSun, faMoon, faCircleHalfStroke, faCheck, faExternalLinkAlt, faDownload, faFileImport, faFileExport, faCopy } from '@fortawesome/free-solid-svg-icons';
import { faGithub } from '@fortawesome/free-brands-svg-icons';
import { CookieService } from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service';
import { map, Observable, of, distinctUntilChanged } from 'rxjs'; import { map, Observable, of, distinctUntilChanged } from 'rxjs';
@ -38,7 +39,8 @@ export class AppComponent implements AfterViewInit {
batchImportStatus = ''; batchImportStatus = '';
importInProgress = false; importInProgress = false;
cancelImportFlag = false; cancelImportFlag = false;
versionInfo: string | null = null; ytDlpVersion: string | null = null;
metubeVersion: string | null = null;
isAdvancedOpen = false; isAdvancedOpen = false;
@ViewChild('queueMasterCheckbox') queueMasterCheckbox: MasterCheckboxComponent; @ViewChild('queueMasterCheckbox') queueMasterCheckbox: MasterCheckboxComponent;
@ -64,6 +66,7 @@ export class AppComponent implements AfterViewInit {
faFileImport = faFileImport; faFileImport = faFileImport;
faFileExport = faFileExport; faFileExport = faFileExport;
faCopy = faCopy; faCopy = faCopy;
faGithub = faGithub;
constructor(public downloads: DownloadsService, private cookieService: CookieService, private http: HttpClient) { constructor(public downloads: DownloadsService, private cookieService: CookieService, private http: HttpClient) {
this.format = cookieService.get('metube_format') || 'any'; this.format = cookieService.get('metube_format') || 'any';
@ -449,13 +452,15 @@ export class AppComponent implements AfterViewInit {
fetchVersionInfo(): void { fetchVersionInfo(): void {
const baseUrl = `${window.location.origin}${window.location.pathname.replace(/\/[^\/]*$/, '/')}`; const baseUrl = `${window.location.origin}${window.location.pathname.replace(/\/[^\/]*$/, '/')}`;
const versionUrl = `${baseUrl}version`; const versionUrl = `${baseUrl}version`;
this.http.get<{ version: string}>(versionUrl) this.http.get<{ 'yt-dlp': string, version: string }>(versionUrl)
.subscribe({ .subscribe({
next: (data) => { next: (data) => {
this.versionInfo = `yt-dlp version: ${data.version}`; this.ytDlpVersion = data['yt-dlp'];
this.metubeVersion = data.version;
}, },
error: () => { error: () => {
this.versionInfo = ''; this.ytDlpVersion = null;
this.metubeVersion = null;
} }
}); });
} }