Skip to content
Snippets Groups Projects
Commit e9c36d9f authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Duncan McNamara
Browse files

Improve the navbar UI and responsiveness

parent 85bf589e
No related branches found
No related tags found
1 merge request!1873Remote access
......@@ -93,5 +93,6 @@ object TranslationMapping {
VIDEO_GROUP_BY_NAME(R.string.video_min_group_length_name),
PLAY_ALL(R.string.play_all),
DARK_THEME(R.string.dark_theme),
LIGHT_THEME(R.string.light_theme),
}
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
\ No newline at end of file
<template>
<nav class="navbar navbar-light navbar-expand-md shadow-sm sticky-top align-items-center container-fluid main-navbar">
<div class="flex1">
<div class="flex1-collapsible">
<RouterLink :to="{ name: 'VideoList' }">
<img id="logo" v-bind:src="$getAppAsset('ic_icon', 48, true)" width="48" v-on:click="iconClick()" v-bind:class="this.clicked > 2 && this.clicked % 2 == 1 ? 'animate' : ''">
<img id="logo" v-bind:src="$getAppAsset('ic_icon', 48, true)" width="48" v-on:click="iconClick()"
v-bind:class="this.clicked > 2 && this.clicked % 2 == 1 ? 'animate' : ''">
</RouterLink>
</div>
<div class="d-flex justify-content-center">
<div class="d-flex justify-content-center nav-collapsed collapsed">
<p class="text-primary nav-main-title">{{ getRouteName() }}</p>
</div>
<div class="dropdown dropstart nav-collapsed">
<ImageButton type="menu" data-bs-toggle="dropdown" aria-expanded="false" />
<ul class="dropdown-menu dropdown-menu-start">
<li>
<RouterLink :to="{ name: 'VideoList' }">
<div class="nav-button d-flex btn btn-lg medium">
<img class="nav-button" v-bind:src="$getAppAsset('ic_video')">
<p class="collapsed-menu-text" v-t="'VIDEO'"></p>
</div>
</RouterLink>
<RouterLink :to="{ name: 'AudioArtists' }">
<div class="nav-button d-flex btn btn-lg medium">
<img v-bind:src="$getAppAsset('ic_menu_audio')">
<p class="collapsed-menu-text" v-t="'AUDIO'"></p>
</div>
</RouterLink>
<RouterLink :to="{ name: 'BrowseList' }">
<div class="nav-button d-flex btn btn-lg medium">
<img v-bind:src="$getAppAsset('ic_folder')">
<p class="collapsed-menu-text" v-t="'BROWSE'"></p>
</div>
</RouterLink>
<RouterLink :to="{ name: 'PlaylistList' }">
<div class="nav-button d-flex btn btn-lg medium">
<img v-bind:src="$getAppAsset('ic_playlist')">
<p class="collapsed-menu-text" v-t="'PLAYLISTS'"></p>
</div>
</RouterLink>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<RouterLink :to="{ name: 'SearchList' }">
<div class="nav-button d-flex btn btn-lg medium">
<img :src="(`./icons/search.svg`)">
<p class="collapsed-menu-text" v-t="'SEARCH'"></p>
</div>
</RouterLink>
</li>
<li>
<RouterLink :to="{ name: 'Logs' }">
<div class="nav-button d-flex btn btn-lg medium">
<img :src="(`./icons/crash.svg`)">
<p class="collapsed-menu-text" v-t="'LOG_FILE'"></p>
</div>
</RouterLink>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<div class="nav-button d-flex btn btn-lg medium" v-on:click="this.$emit('send-files')">
<img :src="(`./icons/file_upload.svg`)">
<p class="collapsed-menu-text" v-t="'SEND_FILES'"></p>
</div>
</li>
<li>
<div class="nav-button d-flex btn btn-lg medium" v-on:click="changeTheme">
<img :src="(`./icons/dark_mode.svg`)" v-show="(!this.appStore.darkTheme)">
<p class="collapsed-menu-text" v-t="'DARK_THEME'" v-show="(!this.appStore.darkTheme)"></p>
<img :src="(`./icons/light_mode.svg`)" v-show="(this.appStore.darkTheme)">
<p class="collapsed-menu-text" v-t="'LIGHT_THEME'" v-show="(this.appStore.darkTheme)"></p>
</div>
</li>
</ul>
</div>
<div class="d-flex justify-content-center nav-collapsible">
<RouterLink :to="{ name: 'VideoList' }">
<button class="btn btn-lg nav-button medium">
<img v-bind:src="$getAppAsset('ic_video')">
......@@ -31,7 +104,7 @@
</button>
</RouterLink>
</div>
<div class="d-flex flex1 justify-content-end">
<div class="d-flex flex1 justify-content-end nav-collapsible">
<ImageButton type="cloud_off" class="blink" v-show="!appStore.socketOpened" v-on:click.stop="disconnectedClicked"
v-tooltip data-bs-placement="bottom" :title="$t('DISCONNECTED')" />
<RouterLink :to="{ name: 'SearchList' }">
......@@ -39,29 +112,40 @@
</RouterLink>
<div class="dropdown dropstart">
<ImageButton type="more_vert" data-bs-toggle="dropdown" aria-expanded="false" />
<ul class="dropdown-menu">
<li>
<a v-on:click="this.$emit('send-files')" v-t="'SEND_FILES'" class="dropdown-item clickable"></a>
</li>
<li>
<RouterLink class="dropdown-item" :to="{ name: 'Logs' }" v-t="'LOG_FILE'">
</RouterLink>
</li>
<li><hr class="dropdown-divider"></li>
<ul class="dropdown-menu nav-dropdown">
<li>
<a v-on:click="changeTheme" class="dropdown-item clickable">
<img class="image-button" :src="(`./icons/checked.svg`)" v-show="(this.appStore.darkTheme)"/>
<span v-t="'DARK_THEME'"></span>
</a>
</li>
<RouterLink :to="{ name: 'Logs' }">
<div class="nav-button d-flex btn btn-lg medium">
<img :src="(`./icons/crash.svg`)">
<p class="collapsed-menu-text" v-t="'LOG_FILE'"></p>
</div>
</RouterLink>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<div class="nav-button d-flex btn btn-lg medium" v-on:click="this.$emit('send-files')">
<img :src="(`./icons/file_upload.svg`)">
<p class="collapsed-menu-text" v-t="'SEND_FILES'"></p>
</div>
</li>
<li>
<div class="nav-button d-flex btn btn-lg medium" v-on:click="changeTheme">
<img :src="(`./icons/dark_mode.svg`)" v-show="(!this.appStore.darkTheme)">
<p class="collapsed-menu-text" v-t="'DARK_THEME'" v-show="(!this.appStore.darkTheme)"></p>
<img :src="(`./icons/light_mode.svg`)" v-show="(this.appStore.darkTheme)">
<p class="collapsed-menu-text" v-t="'LIGHT_THEME'" v-show="(this.appStore.darkTheme)"></p>
</div>
</li>
</ul>
</div>
</div>
<div class="navtabs-container border-bottom" v-show="this.$route.meta.showDisplayBar">
<div class="flex1 d-flex align-items-center">
<ImageButton :type="(this.appStore.displayType[this.$route.name]) ? 'grid_view' : 'view_list'" v-on:click.stop="this.appStore.toggleDisplayType(this.$route.name)"
v-tooltip data-bs-placement="bottom"
:title="$t((this.appStore.displayType[this.$route.name]) ? 'DISPLAY_GRID': 'DISPLAY_LIST')" />
<ImageButton :type="(this.appStore.displayType[this.$route.name]) ? 'grid_view' : 'view_list'"
v-on:click.stop="this.appStore.toggleDisplayType(this.$route.name)" v-tooltip data-bs-placement="bottom"
:title="$t((this.appStore.displayType[this.$route.name]) ? 'DISPLAY_GRID' : 'DISPLAY_LIST')" />
<div class="dropdown" v-show="this.$route.meta.showGrouping">
<button class="btn btn-lg image-button hidden-arrow" type="button" data-bs-toggle="dropdown"
......@@ -87,20 +171,20 @@
</li>
<li class="nav-item">
<RouterLink class="nav-link" v-show="this.$route.meta.isAudio"
v-bind:class="(this.$route.name == 'AudioAlbums') ? 'active text-primary' : ''" :to="{ name: 'AudioAlbums' }"
v-t="'ALBUMS'">
v-bind:class="(this.$route.name == 'AudioAlbums') ? 'active text-primary' : ''"
:to="{ name: 'AudioAlbums' }" v-t="'ALBUMS'">
</RouterLink>
</li>
<li class="nav-item">
<RouterLink class="nav-link" v-show="this.$route.meta.isAudio"
v-bind:class="(this.$route.name == 'AudioTracks') ? 'active text-primary' : ''" :to="{ name: 'AudioTracks' }"
v-t="'TRACKS'">
v-bind:class="(this.$route.name == 'AudioTracks') ? 'active text-primary' : ''"
:to="{ name: 'AudioTracks' }" v-t="'TRACKS'">
</RouterLink>
</li>
<li class="nav-item">
<RouterLink class="nav-link" v-show="this.$route.meta.isAudio"
v-bind:class="(this.$route.name == 'AudioGenres') ? 'active text-primary' : ''" :to="{ name: 'AudioGenres' }"
v-t="'GENRES'"> </RouterLink>
v-bind:class="(this.$route.name == 'AudioGenres') ? 'active text-primary' : ''"
:to="{ name: 'AudioGenres' }" v-t="'GENRES'"> </RouterLink>
</li>
</ul>
......@@ -123,8 +207,7 @@
<div class="flex1 d-flex justify-content-end align-items-center">
<button class="btn btn-lg image-button" v-show="this.$route.meta.showFAB"
v-on:click.stop="$playAll(this.$route)" v-tooltip data-bs-placement="bottom"
:title="$t('PLAY_ALL')">
v-on:click.stop="$playAll(this.$route)" v-tooltip data-bs-placement="bottom" :title="$t('PLAY_ALL')">
<img class="image-button-image" v-bind:src="$getAppAsset('ic_ctx_play_all', 24)">
</button>
<button class="btn btn-lg image-button" v-show="this.$route.meta.showResume"
......@@ -148,10 +231,10 @@ export default {
ImageButton,
},
data() {
return {
clicked: 0
}
},
return {
clicked: 0
}
},
methods: {
disconnectedClicked() {
this.$root.startWebSocket();
......@@ -172,11 +255,33 @@ export default {
isActive(mode) {
return this.appStore.videoGrouping == mode
},
changeTheme () {
changeTheme() {
this.appStore.darkTheme = !this.appStore.darkTheme
},
iconClick() {
this.clicked++
},
getRouteName() {
if (this.$route.matched[0]) {
switch (this.$route.matched[0].name) {
case 'Video':
return this.$t('VIDEO')
case 'Audio':
return this.$t('AUDIO')
case 'Browse':
return this.$t('BROWSE')
case 'Playlist':
return this.$t('PLAYLISTS')
case 'SearchList':
return this.$t('SEARCH')
case 'Logs':
return this.$t('LOG_FILE')
default:
return ""
}
} else {
return ""
}
}
},
computed: {
......@@ -189,6 +294,45 @@ export default {
<style lang='scss'>
@import '../scss/colors.scss';
.nav-main-title {
font-weight: bold;
}
.nav-dropdown a, .nav-collapsed a {
text-decoration: none;
}
.collapsed-menu-text {
margin-left: 8px;
}
.d-flex.nav-collapsed,
.nav-collapsed {
display: none !important;
}
.flex1-collapsible {
flex: 1;
}
@media screen and (max-width: 580px) {
.d-flex.nav-collapsible,
.nav-collapsible {
display: none !important;
}
.d-flex.nav-collapsed,
.nav-collapsed {
display: inherit !important;
}
.flex1-collapsible {
flex: none;
}
}
.navbar.navbar-light {
border-radius: 0;
padding: 0;
......@@ -232,7 +376,7 @@ export default {
}
.navtabs .nav-link {
color: var(--bs-btn-color);
color: var(--bs-btn-color);
}
.navtabs .nav-link.active {
......@@ -264,86 +408,86 @@ export default {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg) translateY(-23px);
}
}
@keyframes bounce {
0% {
animation-timing-function: ease-in;
opacity: 1;
transform: translateY(-23px);
}
24% {
opacity: 1;
}
40% {
animation-timing-function: ease-in;
transform: translateY(-12px);
}
65% {
animation-timing-function: ease-in;
transform: translateY(-6px);
}
82% {
animation-timing-function: ease-in;
transform: translateY(-3px);
}
93% {
animation-timing-function: ease-in;
transform: translateY(-2px);
}
25%,
55%,
75%,
87% {
animation-timing-function: ease-out;
transform: translateY(0px);
}
100% {
animation-timing-function: ease-out;
opacity: 1;
transform: translateY(0px);
}
0% {
animation-timing-function: ease-in;
opacity: 1;
transform: translateY(-23px);
}
24% {
opacity: 1;
}
40% {
animation-timing-function: ease-in;
transform: translateY(-12px);
}
65% {
animation-timing-function: ease-in;
transform: translateY(-6px);
}
82% {
animation-timing-function: ease-in;
transform: translateY(-3px);
}
93% {
animation-timing-function: ease-in;
transform: translateY(-2px);
}
25%,
55%,
75%,
87% {
animation-timing-function: ease-out;
transform: translateY(0px);
}
100% {
animation-timing-function: ease-out;
opacity: 1;
transform: translateY(0px);
}
}
@keyframes jello {
0% {
transform: scale3d(1, 1, 1);
}
0% {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.1, 0.9, 1);
}
30% {
transform: scale3d(1.1, 0.9, 1);
}
40% {
transform: scale3d(0.9, 1.1, 1);
}
40% {
transform: scale3d(0.9, 1.1, 1);
}
50% {
transform: scale3d(1.05, 0.95, 1);
}
50% {
transform: scale3d(1.05, 0.95, 1);
}
65% {
transform: scale3d(0.98, 1.02, 1);
}
65% {
transform: scale3d(0.98, 1.02, 1);
}
75% {
transform: scale3d(1.02, 0.98, 1);
}
75% {
transform: scale3d(1.02, 0.98, 1);
}
100% {
transform: scale3d(1, 1, 1);
}
100% {
transform: scale3d(1, 1, 1);
}
}
</style>
\ No newline at end of file
</style>nav-dropdown
\ No newline at end of file
......@@ -17,7 +17,7 @@ import PlaylistDetails from './pages/PlaylistDetails'
const routes = [
{ path: '/', redirect: '/videos', name: 'Home' },
{
path: '/videos',
path: '/videos', name: 'Video',
children: [
{ path: '', component: VideoList, name: 'VideoList', meta: { showDisplayBar: true, showResume: true, showGrouping: true } },
{ path: 'group/:groupId', component: VideoList, name: 'VideoGroupList', meta: { showDisplayBar: true, showFAB: true, playAllType: "video-group" } },
......@@ -25,7 +25,7 @@ const routes = [
]
},
{
path: '/audio', redirect: '/audio/artists', name: 'AudioArtists',
path: '/audio', redirect: '/audio/artists', name: 'Audio',
children: [
{ path: 'artists', component: AudioArtists, name: 'AudioArtists', meta: { showDisplayBar: true, isAudio: true, showResume: true, showGrouping: false } },
{ path: 'albums', component: AudioAlbums, name: 'AudioAlbums', meta: { showDisplayBar: true, isAudio: true, showResume: true, showGrouping: false } },
......@@ -36,14 +36,14 @@ const routes = [
]
},
{
path: '/browse', meta: { showDisplayBar: true },
path: '/browse', name: 'Browse', meta: { showDisplayBar: true },
children: [
{ path: '', component: BrowseList, name: 'BrowseList', meta: { showDisplayBar: true } },
{ path: ':browseId', component: BrowseChild, name: 'BrowseChild', meta: { showDisplayBar: true, showFAB: true, playAllType: "browser" } },
]
},
{
path: '/playlists', redirect: '/playlists/all', name: 'PlaylistList',
path: '/playlists', redirect: '/playlists/all', name: 'Playlist',
children : [
{path: 'all', component: PlaylistList, name: 'PlaylistList', meta: { showDisplayBar: true }},
{ path: 'playlist/:playlistId', component: PlaylistDetails, name: 'PlaylistDetails', meta: { showDisplayBar: true, isAudio: false, showResume: false, showGrouping: false, showFAB: true, playAllType: "playlist" } }
......
......@@ -342,7 +342,6 @@ body {
.breadcrumb {
margin-top: 4px;
margin-bottom: 4px;
margin-left: 24px;
border: 1px solid var(--hover-gray);
overflow: auto;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment