mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-07-28 13:41:42 +00:00
major redesign: move to rounded and extra spaceous UI
+ fix `play next` bug + add new folder banner image + add new now playing component + move to gray4 for accent color + increase image sizes, for clean UI
This commit is contained in:
parent
a7dc2fa6bd
commit
5476575d10
@ -12,6 +12,7 @@
|
||||
"@vueuse/core": "^8.5.0",
|
||||
"axios": "^0.26.1",
|
||||
"pinia": "^2.0.17",
|
||||
"pinia-plugin-persistedstate": "^2.1.1",
|
||||
"sass": "^1.49.0",
|
||||
"sass-loader": "^10",
|
||||
"vite-svg-loader": "^3.4.0",
|
||||
|
@ -14,9 +14,10 @@
|
||||
<div id="acontent" class="rounded">
|
||||
<router-view />
|
||||
</div>
|
||||
<BottomBar />
|
||||
<SearchInput />
|
||||
<RightSideBar />
|
||||
<Tabs />
|
||||
<!-- <Tabs /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -33,13 +34,14 @@ import handleShortcuts from "@/composables/useKeyboard";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import Modal from "@/components/modal.vue";
|
||||
import NavBar from "@/components/nav/NavBar.vue";
|
||||
import Tabs from "@/components/RightSideBar/Tabs.vue";
|
||||
// import Tabs from "@/components/RightSideBar/Tabs.vue";
|
||||
import ContextMenu from "@/components/contextMenu.vue";
|
||||
import Notification from "@/components/Notification.vue";
|
||||
import Navigation from "@/components/LeftSidebar/Navigation.vue";
|
||||
import nowPlaying from "@/components/LeftSidebar/nowPlaying.vue";
|
||||
import RightSideBar from "@/components/RightSideBar/Main.vue";
|
||||
import SearchInput from "@/components/RightSideBar/SearchInput.vue";
|
||||
import BottomBar from "@/components/BottomBar/BottomBar.vue";
|
||||
|
||||
import { readLocalStorage, writeLocalStorage } from "@/utils";
|
||||
|
||||
|
98
src/assets/images/folderbg.svg
Normal file
98
src/assets/images/folderbg.svg
Normal file
@ -0,0 +1,98 @@
|
||||
<svg width="1600" height="548" viewBox="0 0 1600 548" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_7_2)" filter="url(#filter0_d_7_2)">
|
||||
<path d="M1241.06 372.097L1280.6 358.972C1285.2 357.445 1286.98 353.889 1285.29 348.789L1277.15 324.265C1275.46 319.165 1271.88 317.39 1266.73 319.099L1244.64 326.433C1242.92 327.002 1241.77 326.961 1240.07 326.308L1238.37 325.655C1236.22 324.834 1234.83 324.793 1232.33 325.623L1225.58 327.862C1221.1 329.35 1219.33 332.85 1221 337.878L1230.64 366.93C1232.34 372.054 1235.91 373.806 1241.06 372.097ZM1225.87 336.709C1225.15 334.54 1225.99 332.993 1228.11 332.289L1232.64 330.785C1234.33 330.224 1235.47 330.297 1237.19 330.942L1238.9 331.619C1241.01 332.4 1242.45 332.449 1244.95 331.619L1268 323.968C1270.19 323.24 1271.79 323.981 1272.55 326.269L1273.01 327.675L1227.85 342.667L1225.87 336.709ZM1239.8 367.251C1237.6 367.979 1236.01 367.239 1235.24 364.927L1229.24 346.838L1274.4 331.846L1280.41 349.959C1281.17 352.247 1280.34 353.794 1278.14 354.522L1239.8 367.251Z" fill="#F2F2F2"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_d_7_2)">
|
||||
<path d="M920.83 363.356L946.539 355.986C951.704 354.505 953.602 351.009 952.114 345.819L945.838 323.925C944.876 320.57 943.998 319.149 941.289 317.627L924.921 308.37C922.305 306.899 920.501 306.894 917.483 307.759L905.848 311.095C900.682 312.575 898.785 316.071 900.273 321.261L910.715 357.687C912.21 362.902 915.665 364.837 920.83 363.356ZM919.86 358.514C917.519 359.185 916.007 358.286 915.364 356.041L905.087 320.195C904.45 317.974 905.249 316.386 907.591 315.715L917.874 312.767L921.666 325.995C922.656 329.447 924.847 330.622 928.275 329.639L941.286 325.909L947.3 346.886C947.943 349.131 947.113 350.701 944.772 351.372L919.86 358.514ZM927.519 325.362C926.53 325.646 925.995 325.329 925.711 324.34L922.237 312.222L939.444 321.944L927.519 325.362Z" fill="#F2F2F2"/>
|
||||
</g>
|
||||
<g filter="url(#filter2_d_7_2)">
|
||||
<path d="M920.83 363.356L946.539 355.986C951.704 354.505 953.602 351.009 952.114 345.819L945.838 323.925C944.876 320.57 943.998 319.149 941.289 317.627L924.921 308.37C922.305 306.899 920.501 306.894 917.483 307.759L905.848 311.095C900.682 312.575 898.785 316.071 900.273 321.261L910.715 357.687C912.21 362.902 915.665 364.837 920.83 363.356ZM919.86 358.514C917.519 359.185 916.007 358.286 915.364 356.041L905.087 320.195C904.45 317.974 905.249 316.386 907.591 315.715L917.874 312.767L921.666 325.995C922.656 329.447 924.847 330.622 928.275 329.639L941.286 325.909L947.3 346.886C947.943 349.131 947.113 350.701 944.772 351.372L919.86 358.514ZM927.519 325.362C926.53 325.646 925.995 325.329 925.711 324.34L922.237 312.222L939.444 321.944L927.519 325.362Z" fill="#F2F2F2"/>
|
||||
</g>
|
||||
<g filter="url(#filter3_d_7_2)">
|
||||
<path d="M784.959 386.222L825.55 376.844C830.272 375.753 832.379 372.38 831.169 367.144L825.353 341.967C824.143 336.731 820.745 334.63 815.46 335.851L792.779 341.091C791.017 341.498 789.875 341.35 788.245 340.541L786.615 339.732C784.55 338.714 783.17 338.543 780.601 339.137L773.677 340.736C769.077 341.799 766.983 345.118 768.176 350.281L775.066 380.106C776.282 385.366 779.674 387.443 784.959 386.222ZM773.141 349.572C772.626 347.345 773.603 345.882 775.78 345.379L780.429 344.305C782.166 343.904 783.29 344.082 784.944 344.886L786.58 345.719C788.61 346.694 790.044 346.878 792.613 346.284L816.273 340.818C818.524 340.298 820.043 341.184 820.585 343.533L820.919 344.976L774.554 355.688L773.141 349.572ZM784.152 381.28C781.901 381.8 780.382 380.914 779.834 378.541L775.543 359.97L821.908 349.258L826.204 367.853C826.747 370.202 825.77 371.665 823.52 372.185L784.152 381.28Z" fill="#F2F2F2"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip1_7_2)" filter="url(#filter4_d_7_2)">
|
||||
<path d="M1175.56 503.894L1196.91 519.989C1201.21 523.223 1205.14 522.634 1208.39 518.322L1222.1 500.132C1224.2 497.345 1224.8 495.789 1224.39 492.709L1221.93 474.066C1221.53 471.092 1220.45 469.648 1217.94 467.759L1208.27 460.475C1203.98 457.241 1200.05 457.829 1196.8 462.141L1174 492.404C1170.73 496.736 1171.26 500.66 1175.56 503.894ZM1178.84 500.205C1176.89 498.739 1176.7 496.991 1178.11 495.126L1200.55 465.344C1201.94 463.499 1203.69 463.181 1205.63 464.647L1214.18 471.085L1205.9 482.075C1203.73 484.943 1204.12 487.4 1206.96 489.546L1217.77 497.692L1204.64 515.119C1203.23 516.985 1201.48 517.267 1199.54 515.801L1178.84 500.205ZM1209.92 486.369C1209.1 485.749 1209.03 485.131 1209.65 484.309L1217.24 474.241L1219.83 493.834L1209.92 486.369Z" fill="#F2F2F2"/>
|
||||
</g>
|
||||
<g filter="url(#filter5_d_7_2)">
|
||||
<path d="M1139.29 314.117C1132.34 317.228 1125.57 322.685 1121.15 328.736C1120.32 329.881 1120.52 331.249 1121.6 332.139C1120.46 334.001 1120.66 336.223 1122.27 338.113C1124.35 340.483 1127.29 340.653 1129.65 338.606L1139.05 330.428C1141.39 328.392 1141.58 325.5 1139.53 323.086C1138.67 322.072 1137.62 321.465 1136.52 321.272C1138.09 320.294 1139.7 319.406 1141.33 318.677C1153.86 313.061 1165.63 316.977 1170.78 328.458C1175.92 339.939 1171.02 351.354 1158.49 356.97C1156.86 357.7 1155.14 358.335 1153.35 358.832C1153.92 357.889 1154.16 356.708 1153.99 355.352C1153.56 352.243 1151.28 350.46 1148.2 350.847L1135.84 352.424C1132.71 352.808 1130.91 355.126 1131.29 358.233C1131.63 360.721 1133.16 362.348 1135.28 362.719C1135.25 364.134 1136.14 365.195 1137.55 365.333C1145.01 366.065 1153.6 364.665 1160.54 361.554C1175.83 354.705 1181.74 340.691 1175.34 326.415C1168.95 312.161 1154.57 307.268 1139.29 314.117Z" fill="#333333" fill-opacity="0.01"/>
|
||||
</g>
|
||||
<g filter="url(#filter6_d_7_2)">
|
||||
<path d="M1021.88 49.7976L1032.05 74.5314C1034.09 79.5014 1037.78 81 1042.77 78.9465L1063.84 70.2835C1067.06 68.9559 1068.38 67.9266 1069.59 65.0655L1076.98 47.7724C1078.15 45.0097 1077.96 43.2162 1076.76 40.3132L1072.16 29.1191C1070.12 24.1491 1066.43 22.6505 1061.44 24.704L1026.39 39.1169C1021.38 41.18 1019.83 44.8276 1021.88 49.7976ZM1026.58 48.2971C1025.66 46.0444 1026.38 44.4425 1028.54 43.5542L1063.03 29.3706C1065.17 28.4919 1066.83 29.11 1067.76 31.3627L1071.83 41.2563L1059.1 46.4904C1055.78 47.8562 1054.86 50.1642 1056.21 53.462L1061.36 65.9799L1041.18 74.2799C1039.02 75.1682 1037.37 74.5173 1036.44 72.2646L1026.58 48.2971ZM1060.38 52.2372C1059.99 51.285 1060.24 50.7183 1061.2 50.3267L1072.85 45.532L1065.1 63.71L1060.38 52.2372Z" fill="#F2F2F2"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_7_2" x="1199" y="294" width="109.13" height="109.13" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_7_2" x="599" y="285" width="376.948" height="240.948" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-274" dy="138"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter2_d_7_2" x="873" y="285" width="106.948" height="106.948" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter3_d_7_2" x="748" y="312" width="103.955" height="103.955" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter4_d_7_2" x="1142" y="435" width="120.036" height="120.036" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter5_d_7_2" x="1033" y="285" width="169.719" height="165.719" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-60" dy="56"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter6_d_7_2" x="999" y="0" width="158.416" height="317.416" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="50" dy="209"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_2"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_2" result="shape"/>
|
||||
</filter>
|
||||
<clipPath id="clip0_7_2">
|
||||
<rect width="80" height="80" fill="white" transform="translate(1203 319.204) rotate(-18.3641)"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_7_2">
|
||||
<rect width="80" height="80" fill="white" transform="translate(1194.15 435) rotate(37)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/images/folderbg.webp
Normal file
BIN
src/assets/images/folderbg.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@ -1,6 +1,5 @@
|
||||
.b-bar {
|
||||
height: 100%;
|
||||
padding: $small;
|
||||
|
||||
.grid {
|
||||
background-color: $primary;
|
||||
|
@ -6,7 +6,7 @@
|
||||
"l-sidebar nav search-input"
|
||||
"l-sidebar content r-sidebar"
|
||||
"l-sidebar content r-sidebar"
|
||||
"l-sidebar content tabs";
|
||||
"l-sidebar content bottombar";
|
||||
max-width: 2720px;
|
||||
height: calc(100vh - 1rem);
|
||||
margin: 0 auto;
|
||||
@ -19,7 +19,11 @@
|
||||
|
||||
@include tablet-landscape {
|
||||
grid-template-columns: min-content 1fr;
|
||||
|
||||
grid-template-areas:
|
||||
"l-sidebar nav"
|
||||
"l-sidebar content"
|
||||
"l-sidebar content"
|
||||
"l-sidebar bottombar";
|
||||
.r-sidebar,
|
||||
#tabs,
|
||||
#gsearch-input {
|
||||
@ -32,7 +36,6 @@
|
||||
grid-area: content;
|
||||
max-width: 1955px;
|
||||
overflow: hidden scroll;
|
||||
margin-top: -$small;
|
||||
|
||||
.nav {
|
||||
margin: $small;
|
||||
@ -48,7 +51,6 @@
|
||||
|
||||
.r-sidebar {
|
||||
grid-area: r-sidebar;
|
||||
margin-top: -$small;
|
||||
}
|
||||
|
||||
#gsearch-input {
|
||||
@ -66,7 +68,6 @@
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
grid-area: bottom-bar;
|
||||
height: 4rem;
|
||||
.b-bar {
|
||||
grid-area: bottombar;
|
||||
}
|
||||
|
@ -24,9 +24,17 @@
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.rounded-sm {
|
||||
border-radius: $small;
|
||||
}
|
||||
|
||||
.rounded-md {
|
||||
border-radius: $medium;
|
||||
}
|
||||
|
||||
.circular {
|
||||
border-radius: 20px;
|
||||
}
|
||||
@ -36,7 +44,7 @@
|
||||
}
|
||||
|
||||
.bg-black {
|
||||
background-color: $black;
|
||||
background-color: $gray4;
|
||||
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@ -58,8 +66,8 @@ button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 2rem;
|
||||
background-image: linear-gradient(70deg, $gray3, $gray2);
|
||||
height: 2.25rem;
|
||||
background: linear-gradient(70deg, $gray3, $gray2);
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient(70deg, #234ece, $darkblue);
|
||||
|
@ -3,7 +3,7 @@
|
||||
padding: $smaller;
|
||||
}
|
||||
|
||||
.pad-small {
|
||||
.pad-sm {
|
||||
padding: $small;
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ input[type="range"] {
|
||||
width: calc(100% - 2px);
|
||||
height: 0.3rem;
|
||||
border-radius: 5px;
|
||||
background-size: 0 100%;
|
||||
background: $gray linear-gradient($accent, $accent) no-repeat;
|
||||
background: $gray linear-gradient(90deg, $accent, $accent) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
@ -38,15 +38,15 @@ input[type="range"] {
|
||||
|
||||
/* Input Thumb */
|
||||
input[type="range"]::-webkit-slider-thumb:hover {
|
||||
background: $pink;
|
||||
background: $accent;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb:hover {
|
||||
background: $pink;
|
||||
background: $accent;
|
||||
}
|
||||
|
||||
input[type="range"]::-ms-thumb:hover {
|
||||
background: $pink;
|
||||
background: $accent;
|
||||
}
|
||||
|
||||
/* Input Track */
|
||||
|
@ -39,7 +39,7 @@ $indigo: #5e5ce6;
|
||||
$teal: rgb(64, 200, 224);
|
||||
|
||||
$primary: $gray4;
|
||||
$accent: $red;
|
||||
$accent: $gray1;
|
||||
$secondary: $gray5;
|
||||
$cta: $blue;
|
||||
$danger: $red;
|
||||
@ -48,7 +48,7 @@ $context: $gray;
|
||||
|
||||
// SVG COLORS
|
||||
$default: $accent;
|
||||
$track-btn-svg: $red;
|
||||
$track-btn-svg: $accent;
|
||||
$side-nav-svg: $red;
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
ref="albumheaderthing"
|
||||
:style="{
|
||||
backgroundImage: `linear-gradient(
|
||||
37deg, ${props.album.colors[0]}, ${props.album.colors[3]}
|
||||
37deg, ${album.colors[0]}, ${album.colors[3]}
|
||||
)`,
|
||||
}"
|
||||
>
|
||||
|
@ -1,33 +1,72 @@
|
||||
<template>
|
||||
<div class="b-bar">
|
||||
<div class="grid rounded">
|
||||
<div class="controlsx rounded">
|
||||
<div class="controls-bottom">
|
||||
<HotKeys />
|
||||
<div class="b-bar bg-black pad-medium rounded">
|
||||
<div class="info">
|
||||
<img
|
||||
:src="paths.images.thumb + queue.currenttrack?.image"
|
||||
alt=""
|
||||
class="rounded"
|
||||
/>
|
||||
<div class="tags">
|
||||
<div class="np-artist ellip">
|
||||
<span v-for="artist in putCommas(queue.currenttrack?.artists || ['Artist'])">
|
||||
{{ artist }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="progress progress-bottom">
|
||||
<span class="durationx">{{ formatSeconds(q.track.current_time) }}</span>
|
||||
<Progress />
|
||||
<span class="durationx">{{ formatSeconds(q.length) }}</span>
|
||||
</div>
|
||||
<div class="r-group">
|
||||
<div id="heart" class="image ctrl-btn"></div>
|
||||
<div id="add-to" class="image ctrl-btn"></div>
|
||||
<div id="repeat" class="image ctrl-btn"></div>
|
||||
<div class="np-title ellip">
|
||||
{{ queue.currenttrack?.title || "Track title" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="volume-group"></div>
|
||||
</div>
|
||||
<Progress />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import "@/assets/scss/BottomBar/BottomBar.scss";
|
||||
import { formatSeconds } from "@/utils";
|
||||
import HotKeys from "../LeftSidebar/NP/HotKeys.vue";
|
||||
import { formatSeconds, putCommas } from "@/utils";
|
||||
import Progress from "../LeftSidebar/NP/Progress.vue";
|
||||
|
||||
import useQStore from "@/stores/queue";
|
||||
import { paths } from "@/config";
|
||||
|
||||
const q = useQStore();
|
||||
const queue = useQStore();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.b-bar {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr max-content;
|
||||
border-radius: 1rem;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
padding-bottom: 2rem;
|
||||
|
||||
.info {
|
||||
display: grid;
|
||||
grid-template-columns: max-content 1fr;
|
||||
gap: 1rem;
|
||||
|
||||
img {
|
||||
height: 6rem;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
|
||||
.np-title {
|
||||
font-size: 1.15rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: $small;
|
||||
}
|
||||
|
||||
.np-artist {
|
||||
opacity: 0.75;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -141,8 +141,8 @@ const showContextMenu = (e: Event) => {
|
||||
font-size: 0.75rem;
|
||||
width: max-content;
|
||||
padding: 0.2rem 0.35rem;
|
||||
top: 14.25rem;
|
||||
left: 1.5rem;
|
||||
top: 14rem;
|
||||
left: 2rem;
|
||||
background-color: $black;
|
||||
border-radius: $smaller;
|
||||
box-shadow: 0rem 0rem 1rem rgba(0, 0, 0, 0.438);
|
||||
|
@ -12,14 +12,7 @@
|
||||
<div class="carddd">
|
||||
<div class="info">
|
||||
<div class="btns">
|
||||
<PlayBtnRect
|
||||
:source="playSources.playlist"
|
||||
:store="usePStore"
|
||||
:background="{
|
||||
color: '#fff',
|
||||
isDark: true,
|
||||
}"
|
||||
/>
|
||||
<PlayBtnRect :source="playSources.playlist" :store="usePStore" />
|
||||
<Option @showDropdown="showDropdown" :src="context.src" />
|
||||
</div>
|
||||
<div class="duration">
|
||||
|
@ -23,7 +23,7 @@
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</div>
|
||||
<PlayingFrom :from="queue.from" />
|
||||
<!-- <PlayingFrom :from="queue.from" /> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -87,8 +87,8 @@ onUpdated(() => {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: max-content 1fr max-content;
|
||||
gap: $small;
|
||||
grid-template-rows: max-content 1fr;
|
||||
gap: 1rem;
|
||||
|
||||
.scrollable-r {
|
||||
height: 100%;
|
||||
|
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div
|
||||
class="next-track bg-black"
|
||||
class="next-track bg-black rounded"
|
||||
:class="{ contexton: context_on }"
|
||||
@click="playNext"
|
||||
@contextmenu.prevent="showMenu"
|
||||
>
|
||||
<div class="nextup abs">next up</div>
|
||||
<img :src="paths.images.thumb + track?.image" class="rounded" />
|
||||
<img :src="paths.images.thumb + track?.image" class="rounded-sm" />
|
||||
<div class="tags">
|
||||
<div class="title ellip">{{ track?.title || "Don't click here" }}</div>
|
||||
<div class="artist ellip" v-if="track">
|
||||
@ -43,13 +43,12 @@ function showMenu(e: Event) {
|
||||
|
||||
<style lang="scss">
|
||||
.next-track {
|
||||
border-radius: 0.5rem;
|
||||
position: relative;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: max-content 1fr;
|
||||
gap: 1rem;
|
||||
padding: $small;
|
||||
padding: 1rem;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
|
@ -49,7 +49,7 @@ defineProps<{
|
||||
|
||||
.search-results-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="right-tabs" class="bg-black rounded">
|
||||
<div class="tab-buttons-wrapper">
|
||||
<div id="tabheaders" class="rounded noscroll">
|
||||
<div id="tabheaders" class="rounded-sm noscroll">
|
||||
<div
|
||||
class="tab"
|
||||
v-for="slot in $slots.default()"
|
||||
@ -44,7 +44,7 @@ const s = useSearchStore();
|
||||
justify-content: space-around;
|
||||
margin: 1rem;
|
||||
width: max-content;
|
||||
background: linear-gradient(37deg, $gray3, $gray4, $gray3);
|
||||
background: linear-gradient(37deg, $gray1, $gray2, $gray1);
|
||||
height: 2rem;
|
||||
|
||||
& > * {
|
||||
@ -55,6 +55,7 @@ const s = useSearchStore();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
@ -1,76 +1,55 @@
|
||||
<template>
|
||||
<div id="gsearch-input">
|
||||
<div
|
||||
id="gsearch-input"
|
||||
class="bg-black rounded"
|
||||
:class="{ 'search-focused': focused }"
|
||||
>
|
||||
<div id="ginner" tabindex="0">
|
||||
<div class="icon image"></div>
|
||||
<SearchSvg />
|
||||
<input
|
||||
id="globalsearch"
|
||||
class="rounded"
|
||||
v-model="search.query"
|
||||
placeholder="Search your library"
|
||||
type="search"
|
||||
@focus="focusThis()"
|
||||
@blur="unfocusThis()"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from "vue";
|
||||
import { ref } from "vue";
|
||||
import useSearchStore from "../../stores/search";
|
||||
import SearchSvg from "../../assets/icons/search.svg";
|
||||
|
||||
const search = useSearchStore();
|
||||
let input: HTMLInputElement;
|
||||
|
||||
onMounted(() => {
|
||||
input = document.getElementById("ginner") as HTMLInputElement;
|
||||
});
|
||||
|
||||
function focusThis() {
|
||||
input.classList.add("focused");
|
||||
}
|
||||
|
||||
function unfocusThis() {
|
||||
input.classList.remove("focused");
|
||||
}
|
||||
const focused = ref(false);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#gsearch-input {
|
||||
display: flex;
|
||||
height: max-content;
|
||||
padding: $smaller;
|
||||
|
||||
#ginner {
|
||||
width: 100%;
|
||||
border-radius: 0.4rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
background-color: $red;
|
||||
background-color: $gray4;
|
||||
|
||||
.icon {
|
||||
width: 2.25rem;
|
||||
aspect-ratio: 1;
|
||||
background-image: url("../../assets/icons/search.svg");
|
||||
background-size: 1.5rem;
|
||||
margin-left: $smaller;
|
||||
}
|
||||
align-items: center;
|
||||
gap: $smaller;
|
||||
margin-left: $small;
|
||||
|
||||
input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
border: none;
|
||||
line-height: 2.25rem;
|
||||
color: inherit;
|
||||
font-size: 1rem;
|
||||
background-color: transparent;
|
||||
outline: 2px solid transparent;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.focused {
|
||||
outline: solid $accent;
|
||||
}
|
||||
}
|
||||
.search-focused {
|
||||
outline: solid $accent;
|
||||
}
|
||||
</style>
|
||||
|
@ -8,13 +8,13 @@
|
||||
v-if="modal.component == modal.options.newPlaylist"
|
||||
:track="modal.props.track"
|
||||
@hideModal="hideModal"
|
||||
@title="title"
|
||||
@setTitle="setTitle"
|
||||
/>
|
||||
<UpdatePlaylist
|
||||
:playlist="modal.props"
|
||||
v-if="modal.component == modal.options.updatePlaylist"
|
||||
@hideModal="hideModal"
|
||||
@title="title"
|
||||
@setTitle="setTitle"
|
||||
/>
|
||||
<WelcomeModal v-if="modal.component == modal.options.welcome" />
|
||||
</div>
|
||||
@ -33,7 +33,7 @@ const modal = useModalStore();
|
||||
* Sets the modal title
|
||||
* @param title
|
||||
*/
|
||||
function title(title: string) {
|
||||
function setTitle(title: string) {
|
||||
console.log(title);
|
||||
modal.setTitle(title);
|
||||
}
|
||||
|
@ -30,15 +30,15 @@ const route = useRoute();
|
||||
const playlistStore = usePlaylistStore();
|
||||
|
||||
onMounted(() => {
|
||||
document.getElementById("modal-playlist-name-input").focus();
|
||||
(document.getElementById("modal-playlist-name-input") as HTMLElement).focus();
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "title", title: string): void;
|
||||
(e: "setTitle", title: string): void;
|
||||
(e: "hideModal"): void;
|
||||
}>();
|
||||
|
||||
emit("title", "New Playlist");
|
||||
emit("setTitle", "New Playlist");
|
||||
|
||||
/**
|
||||
* Create a new playlist. If this modal is called with a track,
|
||||
|
@ -65,15 +65,15 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
onMounted(() => {
|
||||
document.getElementById("modal-playlist-name-input").focus();
|
||||
(document.getElementById("modal-playlist-name-input") as HTMLElement).focus();
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "title", title: string): void;
|
||||
(e: "setTitle", title: string): void;
|
||||
(e: "hideModal"): void;
|
||||
}>();
|
||||
|
||||
emit("title", "Update Playlist");
|
||||
emit("setTitle", "Update Playlist");
|
||||
|
||||
function selectFiles() {
|
||||
const input = document.getElementById(
|
||||
|
@ -1,10 +1,7 @@
|
||||
<template>
|
||||
<div class="topnav">
|
||||
<div class="left">
|
||||
<div class="btn">
|
||||
<NavButtons />
|
||||
</div>
|
||||
|
||||
<NavButtons />
|
||||
<div class="info">
|
||||
<APTitle v-show="showAPTitle" />
|
||||
<Playlists v-show="$route.name == Routes.playlists" />
|
||||
@ -15,16 +12,12 @@
|
||||
<div class="center rounded">
|
||||
<Loader />
|
||||
</div>
|
||||
<!-- <div class="right">
|
||||
<Search />
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import NavButtons from "./NavButtons.vue";
|
||||
import Loader from "../shared/Loader.vue";
|
||||
// import Search from "./Search.vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, watch } from "vue";
|
||||
import { Routes } from "@/composables/enums";
|
||||
@ -82,13 +75,11 @@ watch(
|
||||
display: grid;
|
||||
grid-template-columns: 1fr min-content;
|
||||
width: 100%;
|
||||
gap: 1rem;
|
||||
overflow: hidden;
|
||||
|
||||
.left {
|
||||
display: grid;
|
||||
grid-template-columns: max-content 1fr;
|
||||
overflow: hidden;
|
||||
gap: 1rem;
|
||||
|
||||
.info {
|
||||
overflow: hidden;
|
||||
@ -106,11 +97,5 @@ watch(
|
||||
place-items: center;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: $small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,40 +1,41 @@
|
||||
<template>
|
||||
<div id="back-forward">
|
||||
<div class="back image" @click="$router.back()"></div>
|
||||
<div class="forward image" @click="$router.forward()"></div>
|
||||
<div id="back-forward" class="">
|
||||
<button class="back" @click="$router.back()">
|
||||
<ArrowSvg />
|
||||
</button>
|
||||
<button class="forward" @click="$router.forward()">
|
||||
<ArrowSvg />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ArrowSvg from "../../assets/icons/right-arrow.svg";
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#back-forward {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
padding-right: 1rem;
|
||||
margin-right: $small;
|
||||
padding-right: 1.25rem;
|
||||
border-right: 1px solid $gray3;
|
||||
width: 100%;
|
||||
|
||||
& > div {
|
||||
background-color: $gray4;
|
||||
border-radius: $small;
|
||||
height: 2.25rem;
|
||||
width: 2.25rem;
|
||||
cursor: pointer;
|
||||
background-size: 2rem;
|
||||
transition: all .25s ease-in-out;
|
||||
& > * {
|
||||
background-color: $gray3;
|
||||
padding: $small;
|
||||
height: 100%;
|
||||
aspect-ratio: 1;
|
||||
border-radius: $medium;
|
||||
|
||||
&:hover {
|
||||
background-color: $accent;
|
||||
svg {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.back {
|
||||
background-image: url("../../assets/icons/right-arrow.svg");
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.forward {
|
||||
background-image: url("../../assets/icons/right-arrow.svg");
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -47,5 +47,7 @@ const things = computed(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $small;
|
||||
outline: solid 1px $gray3;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,55 +1,28 @@
|
||||
<template>
|
||||
<div
|
||||
class="p-card rounded"
|
||||
id="new-playlist-card"
|
||||
class="p-card new-playlist-card rounded bg-black"
|
||||
@click="Modal.showNewPlaylistModal()"
|
||||
>
|
||||
<div class="gradient rounded"></div>
|
||||
<div class="plus image p-image"></div>
|
||||
<div>New Playlist</div>
|
||||
<div></div>
|
||||
<PlusSvg />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useModalStore from "../../stores/modal";
|
||||
import PlusSvg from "../../assets/icons/plus.svg";
|
||||
|
||||
const Modal = useModalStore();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#new-playlist-card {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
position: relative;
|
||||
.new-playlist-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
.gradient {
|
||||
position: absolute;
|
||||
width: calc(100% - 1.5rem);
|
||||
top: 0.75rem;
|
||||
background-image: linear-gradient(37deg, $red, $blue);
|
||||
background-size: 100%;
|
||||
transition: all 0.5s ease-in-out;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.image {
|
||||
background-image: url("../../assets/icons/plus.svg");
|
||||
background-size: 5rem;
|
||||
z-index: 1;
|
||||
transition: all 0.5s ease-in-out;
|
||||
background-color: transparent;
|
||||
margin-bottom: $small;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.gradient {
|
||||
background-size: 29rem;
|
||||
}
|
||||
.image {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
svg {
|
||||
transform: scale(3);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<router-link
|
||||
:to="{ name: 'PlaylistView', params: { pid: props.playlist.playlistid } }"
|
||||
:playlist="props.playlist"
|
||||
class="p-card rounded"
|
||||
class="p-card rounded bg-black"
|
||||
>
|
||||
<div
|
||||
class="image p-image rounded shadow-sm"
|
||||
@ -37,10 +37,9 @@ const props = defineProps<{
|
||||
<style lang="scss">
|
||||
.p-card {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
padding: 1rem;
|
||||
transition: all 0.25s ease;
|
||||
position: relative;
|
||||
background-color: #1c1c1e80;
|
||||
|
||||
.p-image {
|
||||
min-width: 100%;
|
||||
@ -72,7 +71,7 @@ const props = defineProps<{
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $gray5;
|
||||
background-color: $gray2;
|
||||
|
||||
.drop {
|
||||
transition-delay: 0.75s;
|
||||
|
@ -29,7 +29,6 @@ defineProps<{
|
||||
display: grid;
|
||||
gap: $small;
|
||||
padding: $small;
|
||||
background-color: $gray4;
|
||||
transition: all 0.5s ease;
|
||||
border-radius: .7rem;
|
||||
|
||||
|
@ -32,16 +32,13 @@ defineProps<{
|
||||
border-radius: 0.75rem;
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
padding: 1rem $small;
|
||||
cursor: pointer;
|
||||
|
||||
.artist-image {
|
||||
width: 8rem;
|
||||
height: 8rem;
|
||||
width: 100%;
|
||||
border-radius: 60%;
|
||||
margin-bottom: $small;
|
||||
transition: all 0.5s ease-in-out;
|
||||
transition-delay: 0.25s;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@ -50,27 +47,5 @@ defineProps<{
|
||||
border-radius: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.artist-name {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 510;
|
||||
max-width: 7rem;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
._is_on_sidebar {
|
||||
background-color: $gray4 !important;
|
||||
|
||||
.artist-image {
|
||||
width: 7rem;
|
||||
height: 7rem;
|
||||
|
||||
@include for-desktop-down {
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,14 +2,18 @@
|
||||
<div
|
||||
class="loaderx"
|
||||
:class="{ loader: loader.loading, not_loader: !loader.loading }"
|
||||
@click="modal.showSearchModal"
|
||||
>
|
||||
<div v-if="!loader.loading">🦋</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useLoaderStore from "../../stores/loader";
|
||||
import useLoaderStore from "@/stores/loader";
|
||||
import useModalStore from "@/stores/modal";
|
||||
|
||||
const loader = useLoaderStore();
|
||||
const modal = useModalStore();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -1,21 +1,12 @@
|
||||
<template>
|
||||
<div
|
||||
class="drop-btn rounded shadow-sm"
|
||||
id="option-drop"
|
||||
@click="showDropdown"
|
||||
>
|
||||
<div
|
||||
class="image drop-icon"
|
||||
:class="{ clicked: clicked && src == ContextSrc.PHeader }"
|
||||
></div>
|
||||
</div>
|
||||
<button id="option-drop" @click.stop.prevent="showDropdown">
|
||||
<MoreSvg />
|
||||
</button>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import { ContextSrc } from "../../composables/enums";
|
||||
|
||||
import { onMounted } from "vue";
|
||||
import MoreSvg from "../../assets/icons/more.svg";
|
||||
let elem: DOMRect;
|
||||
const clicked = ref(false);
|
||||
|
||||
defineProps<{
|
||||
src?: string;
|
||||
@ -26,47 +17,24 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
onMounted(() => {
|
||||
elem = document.getElementById("option-drop").getBoundingClientRect();
|
||||
const el = document.getElementById("option-drop") as HTMLElement;
|
||||
elem = el.getBoundingClientRect();
|
||||
});
|
||||
|
||||
function showDropdown(e: Event) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
emit("showDropdown", {
|
||||
clientX: elem.left + 45,
|
||||
clientX: elem.left + 35,
|
||||
clientY: elem.top,
|
||||
});
|
||||
|
||||
clicked.value = true;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.drop-btn {
|
||||
width: 2.5rem;
|
||||
background-color: $accent;
|
||||
transition: all 0.5s ease-in-out;
|
||||
cursor: pointer;
|
||||
#option-drop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.drop-icon {
|
||||
transition: all 0.25s;
|
||||
padding: $small;
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
background-image: url("../../assets/icons/right-arrow.svg");
|
||||
background-size: 1.75rem;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.clicked {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $green;
|
||||
.image {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
svg {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,8 +1,10 @@
|
||||
<template>
|
||||
<div
|
||||
class="play-btn rounded shadow-sm"
|
||||
<button
|
||||
class="play-btn rounded-md"
|
||||
@click="usePlayFrom(source, useQStore, store)"
|
||||
></div>
|
||||
>
|
||||
<PlaySvg />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -12,24 +14,19 @@ import usePlaylistStore from "@/stores/pages/playlist";
|
||||
import usePlayFrom from "@/composables/usePlayFrom";
|
||||
import useQStore from "@/stores/queue";
|
||||
|
||||
import PlaySvg from "../../assets/icons/play.svg";
|
||||
|
||||
defineProps<{
|
||||
source: playSources;
|
||||
store: typeof useAlbumStore | typeof usePlaylistStore;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.play-btn {
|
||||
height: 2.25rem;
|
||||
background-color: $gray3;
|
||||
background-image: url("../../assets/icons/play.svg");
|
||||
background-size: 1.75rem;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
transition: all 0.25s ease-in-out;
|
||||
height: 100%;
|
||||
aspect-ratio: 1;
|
||||
|
||||
&:hover {
|
||||
background-color: $accent;
|
||||
}
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div
|
||||
class="playbtnrect rounded"
|
||||
<button
|
||||
class="playbtnrect"
|
||||
@click="usePlayFrom(source, useQStore, store)"
|
||||
:style="{
|
||||
backgroundColor: background.color,
|
||||
background: background?.color,
|
||||
}"
|
||||
:class="{ playbtnrectdark: background.isDark }"
|
||||
:class="{ playbtnrectdark: background?.isDark }"
|
||||
>
|
||||
<playBtnSvg />
|
||||
<div class="text">Play</div>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -40,24 +40,9 @@ defineProps<{
|
||||
width: 6rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 2.5rem;
|
||||
padding-left: 0.75rem;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: $white;
|
||||
justify-content: center;
|
||||
transition: all 0.5s ease-in-out;
|
||||
|
||||
.icon {
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
background-image: url("../../assets/icons/play.svg");
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon {
|
||||
transform: rotate(120deg);
|
||||
}
|
||||
}
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.playbtnrectdark {
|
||||
|
@ -19,7 +19,7 @@
|
||||
loading="lazy"
|
||||
:src="imguri + track.image"
|
||||
alt=""
|
||||
class="album-art image rounded"
|
||||
class="album-art image rounded-sm"
|
||||
/>
|
||||
<div
|
||||
class="now-playing-track-indicator image"
|
||||
|
@ -11,7 +11,7 @@
|
||||
@contextmenu.prevent="showMenu"
|
||||
>
|
||||
<div class="album-art">
|
||||
<img :src="paths.images.thumb + track.image" alt="" class="rounded" />
|
||||
<img :src="paths.images.thumb + track.image" alt="" class="rounded-sm" />
|
||||
<div
|
||||
class="now-playing-track-indicator image"
|
||||
v-if="isCurrent"
|
||||
|
@ -2,41 +2,36 @@ import { defineStore } from "pinia";
|
||||
import { Playlist, Track } from "../interfaces";
|
||||
|
||||
enum ModalOptions {
|
||||
newPlaylist = "newPlaylist",
|
||||
updatePlaylist = "editPlaylist",
|
||||
welcome = "welcome",
|
||||
newPlaylist,
|
||||
updatePlaylist,
|
||||
welcome,
|
||||
}
|
||||
|
||||
export default defineStore("newModal", {
|
||||
state: () => ({
|
||||
title: "",
|
||||
options: ModalOptions,
|
||||
component: "",
|
||||
component: <any>null,
|
||||
props: <any>{},
|
||||
visible: false,
|
||||
}),
|
||||
actions: {
|
||||
showModal(modalOption: string) {
|
||||
showModal(modalOption: ModalOptions) {
|
||||
this.component = modalOption;
|
||||
this.visible = true;
|
||||
},
|
||||
showNewPlaylistModal(track?: Track) {
|
||||
this.component = ModalOptions.newPlaylist;
|
||||
|
||||
if (track) {
|
||||
this.props.track = track;
|
||||
}
|
||||
|
||||
this.visible = true;
|
||||
this.showModal(ModalOptions.newPlaylist);
|
||||
},
|
||||
showEditPlaylistModal(playlist: Playlist) {
|
||||
this.component = ModalOptions.updatePlaylist;
|
||||
this.props = playlist;
|
||||
this.visible = true;
|
||||
this.showModal(ModalOptions.updatePlaylist);
|
||||
},
|
||||
showWelcomeModal() {
|
||||
this.component = ModalOptions.welcome;
|
||||
this.visible = true;
|
||||
this.showModal(ModalOptions.welcome);
|
||||
},
|
||||
hideModal() {
|
||||
this.visible = false;
|
||||
|
@ -240,19 +240,25 @@ export default defineStore("Queue", {
|
||||
},
|
||||
playTrackNext(track: Track) {
|
||||
const Toast = useNotifStore();
|
||||
|
||||
const nextindex = this.current + 1;
|
||||
const next: Track = this.tracklist[nextindex];
|
||||
|
||||
// if track is already next, skip
|
||||
if (next?.trackid === track.trackid) {
|
||||
Toast.showNotification("Track is already queued", NotifType.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
// if tracklist is empty or current track is last, push track
|
||||
// else insert track after current track
|
||||
if (this.current == this.tracklist.length - 1) {
|
||||
this.tracklist.push(track);
|
||||
} else {
|
||||
const nextindex = this.current + 1;
|
||||
const next: Track = this.tracklist[nextindex];
|
||||
|
||||
if (next.trackid === track.trackid) {
|
||||
Toast.showNotification("Track is already queued", NotifType.Info);
|
||||
return;
|
||||
}
|
||||
this.tracklist.splice(this.current + 1, 0, track);
|
||||
}
|
||||
|
||||
this.tracklist.splice(this.current + 1, 0, track);
|
||||
// save queue
|
||||
this.updateNext(this.current);
|
||||
Toast.showNotification(
|
||||
`Added ${track.title} to queue`,
|
||||
|
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div id="f-view-parent">
|
||||
<div id="scrollable" ref="scrollable">
|
||||
<div class="banner shadow-lg">
|
||||
<div class="banner shadow-lg rounded">
|
||||
<div class="text abs rounded pad-medium">
|
||||
<h3><FolderSvg /> {{ getFolderName($route) }}</h3>
|
||||
</div>
|
||||
<img
|
||||
src="../assets/images/folder.webp"
|
||||
src="@/assets/images/folderbg.webp"
|
||||
alt=""
|
||||
class="rounded"
|
||||
loading="lazy"
|
||||
@ -79,20 +79,16 @@ onBeforeRouteUpdate((to, from) => {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
// display: table-cell;
|
||||
// vertical-align: bottom;
|
||||
background-color: $accent;
|
||||
|
||||
.text {
|
||||
bottom: 1rem;
|
||||
// height: 100%;
|
||||
left: 1rem;
|
||||
// right: 1rem;
|
||||
// width: min-content;
|
||||
width: max-content;
|
||||
max-width: calc(100% - 2rem);
|
||||
background-color: $black;
|
||||
|
||||
@include for-desktop-down {
|
||||
max-width: 31rem;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
@ -110,6 +106,7 @@ onBeforeRouteUpdate((to, from) => {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
object-position: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,11 +25,11 @@ const pStore = usePStore();
|
||||
scrollbar-color: $gray2 transparent;
|
||||
|
||||
.grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||
grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
|
||||
gap: 1rem;
|
||||
|
||||
@include for-desktop-down {
|
||||
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
|
||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||
|
||||
.name {
|
||||
font-size: 0.9rem;
|
||||
|
@ -1732,6 +1732,11 @@ picomatch@^2.0.4, picomatch@^2.2.1:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
pinia-plugin-persistedstate@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-2.1.1.tgz#584c416cdc278689ae9d49483621ec96dcb7d6ef"
|
||||
integrity sha512-HUgsU5IRtM75eAQiIqzT3p1oPEuYH1/B2ipTMU++yE+FV0LkHaBswdKXs0RMWYCmugO8s62oxLTh/N1dLNp+5A==
|
||||
|
||||
pinia@^2.0.17:
|
||||
version "2.0.17"
|
||||
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.17.tgz#f925e5e4f73c15e16dfb4838176a9ca50752f26b"
|
||||
|
Loading…
x
Reference in New Issue
Block a user