[web-src] Include web-src in dist and build web with autotools

This commit is contained in:
Christian Meffert 2025-01-18 08:30:18 +00:00
parent 991ed0e765
commit 89242af3c8
21 changed files with 260 additions and 234 deletions

View File

@ -5,7 +5,7 @@
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/src/owntone", "program": "${workspaceFolder}/src/owntone",
"args": ["-f", "-c", "/data/conf/owntone.conf", "-w", "${workspaceFolder}/htdocs", "-s", "${workspaceFolder}/sqlext/.libs/owntone-sqlext.so"], "args": ["-f", "-c", "/data/conf/owntone.conf", "-w", "${workspaceFolder}/web-src/htdocs", "-s", "${workspaceFolder}/sqlext/.libs/owntone-sqlext.so"],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"externalConsole": false, "externalConsole": false,

View File

@ -16,7 +16,12 @@ endif
BUILT_SOURCES = $(CONF_FILE) $(SYSTEMD_SERVICE_FILE) $(SYSTEMD_TSERVICE_FILE) BUILT_SOURCES = $(CONF_FILE) $(SYSTEMD_SERVICE_FILE) $(SYSTEMD_TSERVICE_FILE)
SUBDIRS = $(LIBRESPOTC_SUBDIR) sqlext src htdocs if COND_WEBINTERFACE
WEBINTERFACE_SRC_SUBDIR = web-src
endif
SUBDIRS = $(LIBRESPOTC_SUBDIR) sqlext src $(WEBINTERFACE_SRC_SUBDIR)
DIST_SUBDIRS = $(SUBDIRS)
dist_man_MANS = owntone.8 dist_man_MANS = owntone.8
@ -105,3 +110,17 @@ $(CONF_FILE): $(srcdir)/$(CONF_FILE).in
$(SYSTEMD_SERVICE_FILE): $(srcdir)/$(SYSTEMD_SERVICE_FILE).in $(SYSTEMD_SERVICE_FILE): $(srcdir)/$(SYSTEMD_SERVICE_FILE).in
$(SYSTEMD_TSERVICE_FILE): $(srcdir)/$(SYSTEMD_TSERVICE_FILE).in $(SYSTEMD_TSERVICE_FILE): $(srcdir)/$(SYSTEMD_TSERVICE_FILE).in
#
# Convenience make goals for the web interface
#
web:
$(MAKE) web -C web-src
web-update:
$(MAKE) web-update -C web-src
web-serve:
$(MAKE) web-serve -C web-src
web-lint:
$(MAKE) web-lint -C web-src
web-format:
$(MAKE) web-format -C web-src

View File

@ -322,11 +322,23 @@ dnl MPD support
OWNTONE_ARG_DISABLE([MPD client protocol support], [mpd], [MPD]) OWNTONE_ARG_DISABLE([MPD client protocol support], [mpd], [MPD])
AM_CONDITIONAL([COND_MPD], [[test "x$enable_mpd" = "xyes"]]) AM_CONDITIONAL([COND_MPD], [[test "x$enable_mpd" = "xyes"]])
AC_PATH_PROG([NPM], [[npm]])
dnl Include default webinterface dnl Include default webinterface
OWNTONE_ARG_DISABLE([include default web interface], [webinterface], [WEBINTERFACE], OWNTONE_ARG_DISABLE([include default web interface], [webinterface], [WEBINTERFACE],
[AS_IF([[test "x$with_libwebsockets" = "xno"]], [AS_IF(
[AC_MSG_ERROR([[Web interface requires libwebsockets >= 2.0.2 (or use --disable-webinterface)]])]) [[test "x$with_libwebsockets" = "xno"]],
]) [AC_MSG_ERROR([[Web interface requires libwebsockets >= 2.0.2 (or use --disable-webinterface)]])],
[[test -z "$NPM"]],
[AS_IF([[test -f "$srcdir/web-src/htdocs/index.html"]],
[AM_MISSING_PROG([NPM], [[npm]])
AC_MSG_NOTICE([[
npm not found, but a prebuilt web interface seems to be present.
If you modify any web interface files, you will need to install it.
]])],
[AC_MSG_ERROR([[npm required, please install it.]])])
]
)])
AM_CONDITIONAL([COND_WEBINTERFACE], [[test "x$enable_webinterface" = "xyes"]]) AM_CONDITIONAL([COND_WEBINTERFACE], [[test "x$enable_webinterface" = "xyes"]])
dnl Creating and defining users and groups dnl Creating and defining users and groups
@ -379,9 +391,9 @@ AC_CONFIG_SUBDIRS([
]) ])
AC_CONFIG_FILES([ AC_CONFIG_FILES([
web-src/Makefile
src/Makefile src/Makefile
sqlext/Makefile sqlext/Makefile
htdocs/Makefile
Makefile Makefile
owntone.spec owntone.spec
]) ])

View File

@ -1,28 +0,0 @@
if COND_WEBINTERFACE
WEBINTERFACE_SRC = \
index.html
endif
htdocsdir = $(datadir)/owntone/htdocs
dist_htdocs_DATA = \
$(WEBINTERFACE_SRC) \
android-chrome-192x192.png \
android-chrome-512x512.png \
apple-touch-icon.png \
browserconfig.xml \
favicon.ico \
favicon-16x16.png \
favicon-32x32.png \
mstile-150x150.png \
safari-pinned-tab.svg \
site.webmanifest
if COND_WEBINTERFACE
htdocsassetsdir = $(datadir)/owntone/htdocs/assets
dist_htdocsassets_DATA = \
assets/index.css \
assets/index.js
endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,25 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="favicon.ico" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="apple-touch-icon.png?ver=2.0"
/>
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png" />
<link rel="manifest" href="site.webmanifest" />
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#00d1b2" />
<meta name="msapplication-TileColor" content="#da532c" />
<meta name="theme-color" content="#ffffff" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OwnTone</title>
<script type="module" crossorigin src="./assets/index.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index.css">
</head>
<body class="has-navbar-fixed-top has-navbar-fixed-bottom">
<div id="app"></div>
</body>
</html>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#107A66;}
.st1{fill:#479386;}
.st2{fill:#00D1B2;}
.st3{fill:#FFFFFF;}
</style>
<path class="st0" d="M390.5,193.9h30.3c18.5,49.6,13.9,104.8-12.7,150.6c-5.1,8.8-11,17.2-17.6,24.9V193.9z"/>
<path class="st1" d="M440.3,163.9h-79.8v269.6C453.8,378.5,488.6,260.8,440.3,163.9L440.3,163.9z"/>
<path class="st2" d="M256,432c-97,0-176-79-176-176S159,80,256,80c26.9-0.1,53.4,6.1,77.5,17.9H187.9v96h99.8v235.2
C277.2,431,266.6,432,256,432z"/>
<path class="st1" d="M157.9,147.8v76.1h99.8v178H256c-80.6,0-146-65.4-145.9-146.1c0-38.7,15.4-75.8,42.7-103.1
C154.4,151,156.1,149.4,157.9,147.8 M256,50C142.2,50,50,142.2,50,256s92.2,206,206,206c20.9,0,41.7-3.2,61.7-9.4V163.9h-99.8v-36
h199.4C378.3,78.6,318.8,49.9,256,50z"/>
<path class="st2" d="M429.7,183.5c19.7,46.8,19.7,99.6,0,146.4c-12.9,30.1-33.2,56.4-59.2,76.3v3.8c48.5-36,77-92.9,77-153.3
c0.1-28.4-6.3-56.4-18.5-82h-3.3C427.1,177.6,428.5,180.5,429.7,183.5z"/>
<path class="st2" d="M434,256.7c0.1-28.5-6.8-56.7-20-82h-3.4c2.4,4.6,4.7,9.3,6.7,14.1c18.3,43.4,18.3,92.4,0,135.8
c-8.8,20.7-21.5,39.6-37.4,55.5c-3,3-6.2,5.9-9.4,8.7v3.9C410.8,359,434,309.2,434,256.7z"/>
<path class="st2" d="M420.5,256.7c0-28.8-7.5-57.1-21.9-82h-3.5c3.7,6.2,6.9,12.7,9.8,19.3c25.6,60.3,11.9,130.1-34.4,176.4v4.2
C402.5,343.7,420.5,301.2,420.5,256.7z"/>
<path class="st2" d="M382.7,174.7h-3.5c5.2,7.8,9.6,16,13.2,24.6c21.3,50.5,12.9,108.7-21.9,151v4.7
C414.2,304.3,419.1,230.8,382.7,174.7z"/>
<path class="st2" d="M370.5,180.7v5.5c26.7,43.2,26.7,97.8,0,141v5.5C401.1,286.7,401.1,226.7,370.5,180.7z"/>
<g>
<path class="st3" d="M417.3,127.9H217.9v36h99.8v288.7c15.1-4.7,29.5-11.2,42.8-19.1V163.9h79.8C433.9,151.1,426.2,139,417.3,127.9
z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -1,42 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3173 6294 c-330 -40 -614 -124 -918 -274 -299 -147 -489 -284 -741
-535 -250 -249 -386 -439 -540 -750 -128 -260 -212 -532 -261 -845 -26 -164
-26 -616 0 -780 87 -555 303 -1035 647 -1435 450 -523 1045 -852 1740 -960
141 -22 515 -31 662 -16 159 17 324 46 461 83 l117 31 0 1973 0 1974 -680 0
-680 0 0 250 0 250 1356 0 1355 0 -22 33 c-12 17 -97 106 -188 197 -250 249
-439 385 -746 535 -310 152 -615 240 -954 274 -140 15 -470 12 -608 -5z m-333
-2354 l680 0 0 -1215 0 -1215 -79 0 c-261 0 -571 79 -836 212 -187 94 -331
197 -488 347 -391 375 -607 885 -607 1431 0 531 200 1020 572 1400 l73 75 3
-517 2 -518 680 0z"/>
<path d="M4930 2920 l0 -1841 23 12 c43 23 193 127 287 199 136 104 389 362
496 505 298 398 476 825 550 1317 21 145 30 505 15 654 -32 315 -117 629 -244
907 l-40 87 -543 0 -544 0 0 -1840z m318 1662 c38 -53 131 -237 168 -332 90
-231 133 -441 141 -686 9 -264 -21 -479 -103 -724 -74 -222 -168 -402 -313
-594 -60 -80 -66 -86 -69 -61 -3 18 8 41 36 78 518 678 555 1608 94 2325 -13
20 -13 22 6 22 11 0 30 -13 40 -28z m234 -34 c134 -260 208 -493 249 -788 18
-128 15 -432 -6 -575 -67 -464 -269 -887 -584 -1225 -63 -67 -70 -72 -71 -50
0 18 21 50 71 105 370 411 569 927 569 1473 0 343 -73 659 -223 962 -39 80
-73 148 -75 153 -2 4 6 7 17 7 15 0 29 -16 53 -62z m234 -58 c89 -197 151
-405 191 -645 25 -153 25 -542 0 -700 -87 -556 -349 -1057 -743 -1423 -74 -69
-90 -79 -92 -63 -2 15 27 51 105 128 366 365 593 798 684 1308 27 150 37 491
20 646 -32 283 -110 556 -222 781 -22 43 -39 80 -39 83 0 4 10 5 22 3 18 -2
33 -26 74 -118z m193 18 c382 -906 225 -1946 -407 -2698 -91 -109 -242 -257
-354 -348 -71 -58 -78 -61 -78 -40 0 18 27 47 112 119 177 150 371 375 505
586 85 136 207 394 257 543 49 150 86 307 113 480 23 154 23 527 0 683 -36
236 -101 471 -183 663 -24 57 -44 106 -44 109 0 3 8 5 18 5 13 0 29 -27 61
-102z m-775 -95 c107 -189 188 -424 222 -639 25 -165 23 -424 -5 -588 -40
-231 -111 -430 -219 -620 -50 -85 -57 -95 -60 -71 -3 19 16 65 56 144 110 212
168 393 197 617 49 376 -30 795 -211 1118 -24 43 -44 91 -44 107 0 16 2 29 4
29 3 0 30 -44 60 -97z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,19 +0,0 @@
{
"name": "OwnTone",
"short_name": "OwnTone",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

1
web-src/.gitignore vendored
View File

@ -62,6 +62,7 @@ typings/
# dist directory # dist directory
dist/ dist/
htdocs/
# Visual Studio Code files # Visual Studio Code files
.vscode/ .vscode/

221
web-src/Makefile.am Normal file
View File

@ -0,0 +1,221 @@
WEB_BUILD_DIR = htdocs
PACKAGE_JSON = package-lock.json \
package.json
WEB_DIRS = public \
src \
src/components \
src/filter \
src/i18n \
src/lib \
src/pages \
src/router \
src/stores \
src/templates \
src/webapi
WEB_FILES = \
public/android-chrome-512x512.png \
public/mstile-150x150.png \
public/browserconfig.xml \
public/site.webmanifest \
public/favicon.ico \
public/android-chrome-192x192.png \
public/safari-pinned-tab.svg \
public/apple-touch-icon.png \
public/favicon-16x16.png \
public/logo.svg \
public/favicon-32x32.png \
src/components/ModalDialogAddRss.vue \
src/components/ModalDialogPlaylistSpotify.vue \
src/components/ListPlaylistsSpotify.vue \
src/components/ListArtistsSpotify.vue \
src/components/ModalDialogComposer.vue \
src/components/ListArtists.vue \
src/components/ControlSlider.vue \
src/components/ModalDialogArtist.vue \
src/components/ListPlaylists.vue \
src/components/ModalDialogArtistSpotify.vue \
src/components/ModalDialogPlaylistSave.vue \
src/components/ModalDialogGenre.vue \
src/components/ModalDialogTrackSpotify.vue \
src/components/ListTracks.vue \
src/components/ListGenres.vue \
src/components/ModalDialogAlbumSpotify.vue \
src/components/TabsAudiobooks.vue \
src/components/IndexButtonList.vue \
src/components/TabsSettings.vue \
src/components/ModalDialogAddUrlStream.vue \
src/components/ModalDialogDirectory.vue \
src/components/ListComposers.vue \
src/components/CoverArtwork.vue \
src/components/NavbarItemOutput.vue \
src/components/ModalDialogAlbum.vue \
src/components/ControlDropdown.vue \
src/components/ModalDialogPlaylist.vue \
src/components/ListDirectories.vue \
src/components/ModalDialog.vue \
src/components/ListAlbums.vue \
src/components/ListAlbumsSpotify.vue \
src/components/ListItemQueueItem.vue \
src/components/ListTracksSpotify.vue \
src/components/LyricsPane.vue \
src/components/ModalDialogQueueItem.vue \
src/components/ModalDialogRemotePairing.vue \
src/components/ModalDialogTrack.vue \
src/components/ModalDialogUpdate.vue \
src/components/NavbarBottom.vue \
src/components/NavbarItemLink.vue \
src/components/NavbarTop.vue \
src/components/NotificationList.vue \
src/components/PlayerButtonConsume.vue \
src/components/PlayerButtonLyrics.vue \
src/components/PlayerButtonNext.vue \
src/components/PlayerButtonPlayPause.vue \
src/components/PlayerButtonPrevious.vue \
src/components/PlayerButtonRepeat.vue \
src/components/PlayerButtonSeekBack.vue \
src/components/PlayerButtonSeekForward.vue \
src/components/PlayerButtonShuffle.vue \
src/components/SettingsCheckbox.vue \
src/components/SettingsIntfield.vue \
src/components/SettingsTextfield.vue \
src/components/TabsMusic.vue \
src/components/TabsSearch.vue \
src/filter/index.js \
src/i18n/index.js \
src/i18n/de.json \
src/i18n/en.json \
src/i18n/fr.json \
src/i18n/zh-CN.json \
src/i18n/zh-TW.json \
src/lib/Audio.js \
src/lib/SVGRenderer.js \
src/lib/GroupedList.js \
src/pages/PageMusicRecentlyPlayed.vue \
src/pages/PageMusicSpotifyFeaturedPlaylists.vue \
src/pages/PageAudiobooksArtists.vue \
src/pages/PageAudiobooksGenres.vue \
src/pages/PageAlbum.vue \
src/pages/PageComposerAlbums.vue \
src/pages/PageMusicSpotify.vue \
src/pages/PagePlaylistTracks.vue \
src/pages/PagePodcast.vue \
src/pages/PageMusicSpotifyNewReleases.vue \
src/pages/PageRadioStreams.vue \
src/pages/PageAudiobooksAlbums.vue \
src/pages/PageComposers.vue \
src/pages/PageAudiobooksArtist.vue \
src/pages/PageGenres.vue \
src/pages/PageMusic.vue \
src/pages/PageGenreAlbums.vue \
src/pages/PageAbout.vue \
src/pages/PageAlbumSpotify.vue \
src/pages/PageAlbums.vue \
src/pages/PageArtist.vue \
src/pages/PageArtistSpotify.vue \
src/pages/PageArtistTracks.vue \
src/pages/PageArtists.vue \
src/pages/PageComposerTracks.vue \
src/pages/PageFiles.vue \
src/pages/PageGenreTracks.vue \
src/pages/PageMusicRecentlyAdded.vue \
src/pages/PagePlaylistFolder.vue \
src/pages/PagePlaylistTracksSpotify.vue \
src/pages/PagePodcasts.vue \
src/pages/PageQueue.vue \
src/pages/PageSearchLibrary.vue \
src/pages/PageSearchSpotify.vue \
src/pages/PageSettingsOnlineServices.vue \
src/pages/PageSettingsRemotesOutputs.vue \
src/pages/PageAudiobooksAlbum.vue \
src/pages/PageNowPlaying.vue \
src/pages/PageSettingsArtwork.vue \
src/pages/PageSettingsWebinterface.vue \
src/router/index.js \
src/stores/configuration.js \
src/stores/library.js \
src/stores/lyrics.js \
src/stores/notifications.js \
src/stores/outputs.js \
src/stores/player.js \
src/stores/queue.js \
src/stores/remotes.js \
src/stores/search.js \
src/stores/services.js \
src/stores/settings.js \
src/stores/ui.js \
src/templates/ContentWithHeading.vue \
src/templates/ContentWithHero.vue \
src/webapi/index.js \
src/App.vue \
src/icons.js \
src/main.js \
src/mystyles.scss \
.prettierrc.json \
eslint.config.js \
index.html \
jsconfig.json \
$(PACKAGE_JSON) \
vite.config.js
EXTRA_DIST = $(WEB_FILES) htdocs
node_modules: $(PACKAGE_JSON)
@if [ "$(abs_srcdir)" = "$(abs_builddir)" ]; then \
echo "In-tree build detected"; \
else \
echo "Out-of-tree build detected, copy source files to build dir"; \
for dir in $(WEB_DIRS); do \
dest_dir="$(abs_builddir)/$$dir"; \
mkdir -p "$$dest_dir"; \
done; \
for file in $(WEB_FILES); do \
src_path="$(abs_srcdir)/$$file"; \
dest_path="$(abs_builddir)/$$file"; \
cp "$$src_path" "$$dest_path"; \
done; \
fi
$(if $(NPM),$(NPM) clean-install)
# Build the Vue.js application
htdocs: node_modules $(WEB_FILES)
$(if $(NPM),$(NPM) run build)
web: htdocs
web-serve: node_modules
$(if $(NPM),$(NPM) run serve)
web-update:
$(if $(NPM),$(NPM) update)
web-lint: node_modules
$(if $(NPM),$(NPM) run lint)
web-format: node_modules
$(if $(NPM),$(NPM) run format)
all-local: htdocs
install-data-local:
mkdir -p $(DESTDIR)$(datadir)/owntone/htdocs
cp -r $(WEB_BUILD_DIR)/* $(DESTDIR)$(datadir)/owntone/htdocs
uninstall-local:
rm -rf $(DESTDIR)$(datadir)/owntone/htdocs
# Clean up Vue.js build artifacts
clean-local:
rm -rf $(WEB_BUILD_DIR)
distclean-local:
@if [ "$(abs_srcdir)" != "$(abs_builddir)" ]; then \
echo "Cleaning up copied files from out-of-tree build..."; \
for file in $(WEB_FILES); do \
rm -f "$(abs_builddir)/$$file"; \
done; \
fi
rm -rf node_modules

View File

@ -13,7 +13,7 @@ const target = process.env.VITE_OWNTONE_URL ?? 'http://localhost:3689'
export default defineConfig({ export default defineConfig({
build: { build: {
outDir: '../htdocs', outDir: './htdocs',
rollupOptions: { rollupOptions: {
output: { output: {
assetFileNames: `assets/[name].[ext]`, assetFileNames: `assets/[name].[ext]`,