App.vue 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. <template>
  2. <div class="upper-container">
  3. <banned v-if="banned" />
  4. <div v-else class="upper-container">
  5. <router-view
  6. :key="$route.fullPath"
  7. class="main-container"
  8. :class="{ 'main-container-modal-active': aModalIsOpen }"
  9. />
  10. <what-is-new v-show="modals.whatIsNew" />
  11. <login-modal v-if="modals.login" />
  12. <register-modal v-if="modals.register" />
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. import { mapState, mapActions, mapGetters } from "vuex";
  18. import Toast from "toasters";
  19. import ws from "./ws";
  20. import aw from "./aw";
  21. import keyboardShortcuts from "./keyboardShortcuts";
  22. export default {
  23. components: {
  24. WhatIsNew: () => import("@/components/modals/WhatIsNew.vue"),
  25. LoginModal: () => import("@/components/modals/Login.vue"),
  26. RegisterModal: () => import("@/components/modals/Register.vue"),
  27. Banned: () => import("@/pages/Banned.vue")
  28. },
  29. replace: false,
  30. data() {
  31. return {
  32. apiDomain: "",
  33. socketConnected: true,
  34. keyIsDown: false
  35. };
  36. },
  37. computed: {
  38. ...mapState({
  39. loggedIn: state => state.user.auth.loggedIn,
  40. role: state => state.user.auth.role,
  41. username: state => state.user.auth.username,
  42. userId: state => state.user.auth.userId,
  43. banned: state => state.user.auth.banned,
  44. modals: state => state.modalVisibility.modals,
  45. currentlyActive: state => state.modalVisibility.currentlyActive,
  46. nightmode: state => state.user.preferences.nightmode,
  47. activityWatch: state => state.user.preferences.activityWatch
  48. }),
  49. ...mapGetters({
  50. socket: "websockets/getSocket"
  51. }),
  52. aModalIsOpen() {
  53. return Object.keys(this.currentlyActive).length > 0;
  54. }
  55. },
  56. watch: {
  57. socketConnected(connected) {
  58. if (!connected) this.disconnectedMessage.show();
  59. else this.disconnectedMessage.hide();
  60. },
  61. nightmode(nightmode) {
  62. if (nightmode) this.enableNightMode();
  63. else this.disableNightMode();
  64. },
  65. activityWatch(activityWatch) {
  66. if (activityWatch) aw.enable();
  67. else aw.disable();
  68. }
  69. },
  70. async mounted() {
  71. document.onkeydown = ev => {
  72. const event = ev || window.event;
  73. const { keyCode } = event;
  74. const shift = event.shiftKey;
  75. const ctrl = event.ctrlKey;
  76. const alt = event.altKey;
  77. const identifier = `${keyCode}.${shift}.${ctrl}`;
  78. if (this.keyIsDown === identifier) return;
  79. this.keyIsDown = identifier;
  80. keyboardShortcuts.handleKeyDown(event, keyCode, shift, ctrl, alt);
  81. };
  82. document.onkeyup = () => {
  83. this.keyIsDown = "";
  84. };
  85. keyboardShortcuts.registerShortcut("closeModal", {
  86. keyCode: 27,
  87. shift: false,
  88. ctrl: false,
  89. handler: () => {
  90. if (Object.keys(this.currentlyActive).length !== 0)
  91. this.closeCurrentModal();
  92. }
  93. });
  94. if (localStorage.getItem("github_redirect")) {
  95. this.$router.push(localStorage.getItem("github_redirect"));
  96. localStorage.removeItem("github_redirect");
  97. }
  98. this.disconnectedMessage = new Toast({
  99. content: "Could not connect to the server.",
  100. persistent: true,
  101. interactable: false
  102. });
  103. this.disconnectedMessage.hide();
  104. ws.onConnect(true, () => {
  105. this.socketConnected = true;
  106. });
  107. ws.onDisconnect(true, () => {
  108. this.socketConnected = false;
  109. });
  110. this.apiDomain = await lofig.get("apiDomain");
  111. this.$router.onReady(() => {
  112. if (this.$route.query.err) {
  113. let { err } = this.$route.query;
  114. err = err
  115. .replace(new RegExp("<", "g"), "&lt;")
  116. .replace(new RegExp(">", "g"), "&gt;");
  117. this.$router.push({ query: {} });
  118. new Toast({ content: err, timeout: 20000 });
  119. }
  120. if (this.$route.query.msg) {
  121. let { msg } = this.$route.query;
  122. msg = msg
  123. .replace(new RegExp("<", "g"), "&lt;")
  124. .replace(new RegExp(">", "g"), "&gt;");
  125. this.$router.push({ query: {} });
  126. new Toast({ content: msg, timeout: 20000 });
  127. }
  128. });
  129. this.socket.dispatch("users.getPreferences", res => {
  130. if (res.status === "success") {
  131. const { preferences } = res.data;
  132. this.changeAutoSkipDisliked(preferences.autoSkipDisliked);
  133. this.changeNightmode(preferences.nightmode);
  134. this.changeActivityLogPublic(preferences.activityLogPublic);
  135. this.changeAnonymousSongRequests(
  136. preferences.anonymousSongRequests
  137. );
  138. this.changeActivityWatch(preferences.activityWatch);
  139. if (this.nightmode) this.enableNightMode();
  140. else this.disableNightMode();
  141. }
  142. });
  143. this.socket.on("keep.event:user.session.deleted", () =>
  144. window.location.reload()
  145. );
  146. },
  147. methods: {
  148. submitOnEnter: (cb, event) => {
  149. if (event.which === 13) cb();
  150. },
  151. enableNightMode: () => {
  152. document
  153. .getElementsByTagName("body")[0]
  154. .classList.add("night-mode");
  155. },
  156. disableNightMode: () => {
  157. document
  158. .getElementsByTagName("body")[0]
  159. .classList.remove("night-mode");
  160. },
  161. ...mapActions("modalVisibility", ["closeCurrentModal"]),
  162. ...mapActions("user/preferences", [
  163. "changeNightmode",
  164. "changeAutoSkipDisliked",
  165. "changeActivityLogPublic",
  166. "changeAnonymousSongRequests",
  167. "changeActivityWatch"
  168. ])
  169. }
  170. };
  171. </script>
  172. <style lang="scss">
  173. :root {
  174. --primary-color: var(--blue);
  175. --blue: rgb(2, 166, 242);
  176. --light-blue: rgb(163, 224, 255);
  177. --dark-blue: rgb(0, 102, 244);
  178. --teal: rgb(0, 209, 178);
  179. --purple: rgb(143, 40, 140);
  180. --light-purple: rgb(170, 141, 216);
  181. --yellow: rgb(241, 196, 15);
  182. --light-pink: rgb(228, 155, 166);
  183. --dark-pink: rgb(234, 72, 97);
  184. --orange: rgb(255, 94, 0);
  185. --dark-orange: rgb(250, 50, 0);
  186. --green: rgb(68, 189, 50);
  187. --red: rgb(231, 77, 60);
  188. --white: rgb(255, 255, 255);
  189. --black: rgb(0, 0, 0);
  190. --light-grey: rgb(245, 245, 245);
  191. --light-grey-2: rgb(221, 221, 221);
  192. --light-grey-3: rgb(195, 193, 195);
  193. --grey: rgb(107, 107, 107);
  194. --grey-2: rgb(113, 113, 113);
  195. --grey-3: rgb(126, 126, 126);
  196. --dark-grey: rgb(77, 77, 77);
  197. --dark-grey-2: rgb(51, 51, 51);
  198. --dark-grey-3: rgb(34, 34, 34);
  199. --dark-grey-4: rgb(26, 26, 26);
  200. --youtube: rgb(189, 46, 46);
  201. }
  202. .night-mode {
  203. div {
  204. // background-color: var(--black);
  205. color: var(--light-grey-2);
  206. }
  207. #toasts-container .toast {
  208. // color: var(--dark-grey-2);
  209. // background-color: var(--light-grey-3) !important;
  210. // &:last-of-type {
  211. // background-color: var(--light-grey) !important;
  212. // }
  213. }
  214. h1,
  215. h2,
  216. h3,
  217. h4,
  218. h5,
  219. h6 {
  220. color: var(--white) !important;
  221. }
  222. p:not(.help),
  223. label,
  224. .label {
  225. color: var(--light-grey-2) !important;
  226. }
  227. .section,
  228. .content {
  229. background-color: var(--dark-grey-3) !important;
  230. }
  231. .content-box,
  232. .step:not(.selected) {
  233. background-color: var(--dark-grey-3) !important;
  234. }
  235. .tippy-tooltip.songActions-theme {
  236. background-color: var(--dark-grey);
  237. }
  238. }
  239. body.night-mode {
  240. background-color: var(--black) !important;
  241. }
  242. #toasts-container {
  243. z-index: 10000 !important;
  244. .toast {
  245. font-weight: 600;
  246. // background-color: var(--dark-grey) !important;
  247. // &:last-of-type {
  248. // background-color: var(--dark-grey-2) !important;
  249. // }
  250. }
  251. }
  252. html {
  253. overflow: auto !important;
  254. height: 100%;
  255. }
  256. body {
  257. background-color: var(--light-grey);
  258. color: var(--dark-grey);
  259. height: 100%;
  260. font-family: "Inter", Helvetica, Arial, sans-serif;
  261. }
  262. h1,
  263. h2,
  264. h3,
  265. h4,
  266. h5,
  267. h6,
  268. .sidebar-title {
  269. font-family: "Inter", Helvetica, Arial, sans-serif;
  270. }
  271. .modal-card-title {
  272. font-weight: 600;
  273. font-family: "Inter", Helvetica, Arial, sans-serif;
  274. }
  275. p,
  276. button,
  277. input,
  278. select,
  279. textarea {
  280. font-family: "Inter", Helvetica, Arial, sans-serif;
  281. }
  282. .upper-container {
  283. height: 100%;
  284. }
  285. .main-container {
  286. height: 100%;
  287. display: flex;
  288. flex-direction: column;
  289. > .container {
  290. flex: 1 0 auto;
  291. }
  292. }
  293. .main-container.main-container-modal-active {
  294. height: 100% !important;
  295. overflow: hidden;
  296. }
  297. a {
  298. color: var(--primary-color);
  299. text-decoration: none;
  300. }
  301. .modal-card {
  302. margin: 0 !important;
  303. }
  304. .absolute-a {
  305. width: 100%;
  306. height: 100%;
  307. position: absolute;
  308. top: 0;
  309. left: 0;
  310. }
  311. .alert {
  312. padding: 20px;
  313. color: var(--white);
  314. background-color: var(--red);
  315. position: fixed;
  316. top: 50px;
  317. right: 50px;
  318. font-size: 2em;
  319. border-radius: 5px;
  320. z-index: 10000000;
  321. }
  322. .tippy-tooltip.dark-theme {
  323. font-size: 14px;
  324. padding: 5px 10px;
  325. }
  326. .night-mode {
  327. .tippy-tooltip {
  328. &.dark-theme {
  329. border: 1px solid var(--light-grey-3);
  330. box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25),
  331. 0 10px 10px rgba(0, 0, 0, 0.22);
  332. background-color: white;
  333. .tippy-content {
  334. color: var(--black);
  335. }
  336. }
  337. &.songActions-theme {
  338. background-color: var(--dark-grey-2);
  339. border: 0 !important;
  340. i,
  341. a {
  342. color: var(--white);
  343. }
  344. .youtube-icon {
  345. background-color: var(--white);
  346. }
  347. }
  348. &.addToPlaylist-theme {
  349. background-color: var(--dark-grey-2);
  350. border: 0 !important;
  351. .nav-dropdown-items {
  352. .nav-item {
  353. background-color: var(--dark-grey);
  354. &:focus {
  355. outline-color: var(--dark-grey);
  356. }
  357. p {
  358. color: var(--white);
  359. }
  360. }
  361. }
  362. }
  363. }
  364. .tippy-popper[x-placement^="top"] .tippy-tooltip {
  365. &.songActions-theme,
  366. &.addToPlaylist-theme {
  367. .tippy-arrow {
  368. border-top-color: var(--dark-grey-2);
  369. }
  370. }
  371. &.dark-theme .tippy-arrow {
  372. border-top-color: var(--white);
  373. }
  374. }
  375. .tippy-popper[x-placement^="bottom"] .tippy-tooltip {
  376. &.songActions-theme,
  377. &.addToPlaylist-theme {
  378. .tippy-arrow {
  379. border-bottom-color: var(--dark-grey-2);
  380. }
  381. }
  382. &.dark-theme .tippy-arrow {
  383. border-bottom-color: var(--white);
  384. }
  385. }
  386. .tippy-popper[x-placement^="left"] .tippy-tooltip {
  387. &.songActions-theme,
  388. &.addToPlaylist-theme {
  389. .tippy-arrow {
  390. border-left-color: var(--dark-grey-2);
  391. }
  392. }
  393. &.dark-theme .tippy-arrow {
  394. border-left-color: var(--white);
  395. }
  396. }
  397. .tippy-popper[x-placement^="right"] .tippy-tooltip {
  398. &.songActions-theme,
  399. &.addToPlaylist-theme {
  400. .tippy-arrow {
  401. border-right-color: var(--dark-grey-2);
  402. }
  403. }
  404. &.dark-theme .tippy-arrow {
  405. border-right-color: var(--white);
  406. }
  407. }
  408. }
  409. .tippy-tooltip.info-theme {
  410. font-size: 12px;
  411. letter-spacing: 1px;
  412. }
  413. .tippy-tooltip.confirm-theme {
  414. background-color: var(--red);
  415. padding: 5px 10px;
  416. a {
  417. color: var(--white);
  418. font-size: 15px;
  419. font-weight: 600;
  420. &:hover,
  421. &:focus {
  422. filter: brightness(90%);
  423. }
  424. }
  425. }
  426. .tippy-tooltip.songActions-theme {
  427. font-size: 15px;
  428. padding: 5px 10px;
  429. border: 1px solid var(--light-grey-3);
  430. box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
  431. background-color: var(--white);
  432. .button {
  433. width: 146px;
  434. }
  435. .song-actions,
  436. .addToPlaylistDropdown,
  437. .song-actions > div {
  438. display: inline-block;
  439. }
  440. .addToPlaylistDropdown .tippy-popper {
  441. max-width: unset;
  442. }
  443. i,
  444. a {
  445. display: inline-block;
  446. cursor: pointer;
  447. color: var(--dark-grey);
  448. vertical-align: middle;
  449. &:hover,
  450. &:focus {
  451. filter: brightness(90%);
  452. }
  453. &:not(:first) {
  454. margin-left: 5px;
  455. }
  456. }
  457. .play-icon {
  458. color: var(--green);
  459. }
  460. .edit-icon,
  461. .view-icon,
  462. .add-to-playlist-icon,
  463. .add-to-queue-icon {
  464. color: var(--primary-color);
  465. }
  466. .hide-icon {
  467. color: var(--light-grey-3);
  468. }
  469. .stop-icon,
  470. .delete-icon {
  471. color: var(--red);
  472. }
  473. .report-icon {
  474. color: var(--yellow);
  475. }
  476. }
  477. .tippy-popper[x-placement^="top"] .tippy-tooltip {
  478. &.songActions-theme,
  479. &.addToPlaylist-theme {
  480. .tippy-arrow {
  481. border-top-color: var(--white);
  482. }
  483. }
  484. &.confirm-theme .tippy-arrow {
  485. border-top-color: var(--red);
  486. }
  487. }
  488. .tippy-popper[x-placement^="bottom"] .tippy-tooltip {
  489. &.songActions-theme,
  490. &.addToPlaylist-theme {
  491. .tippy-arrow {
  492. border-bottom-color: var(--white);
  493. }
  494. }
  495. &.confirm-theme .tippy-arrow {
  496. border-bottom-color: var(--red);
  497. }
  498. }
  499. .tippy-popper[x-placement^="left"] .tippy-tooltip {
  500. &.songActions-theme,
  501. &.addToPlaylist-theme {
  502. .tippy-arrow {
  503. border-left-color: var(--white);
  504. }
  505. }
  506. &.confirm-theme .tippy-arrow {
  507. border-left-color: var(--red);
  508. }
  509. }
  510. .tippy-popper[x-placement^="right"] .tippy-tooltip {
  511. &.songActions-theme,
  512. &.addToPlaylist-theme {
  513. .tippy-arrow {
  514. border-right-color: var(--white);
  515. }
  516. }
  517. &.confirm-theme .tippy-arrow {
  518. border-right-color: var(--red);
  519. }
  520. }
  521. .tippy-tooltip.addToPlaylist-theme {
  522. font-size: 15px;
  523. padding: 5px;
  524. border: 1px solid var(--light-grey-3);
  525. box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
  526. background-color: var(--white);
  527. color: var(--dark-grey);
  528. .nav-dropdown-items {
  529. .nav-item {
  530. width: 100%;
  531. justify-content: flex-start;
  532. border: 0;
  533. padding: 10px;
  534. font-size: 15.5px;
  535. height: 36px;
  536. background: var(--light-grey);
  537. border-radius: 5px;
  538. cursor: pointer;
  539. .checkbox-control {
  540. display: flex;
  541. flex-direction: row;
  542. align-items: center;
  543. p {
  544. margin-left: 10px;
  545. }
  546. .switch {
  547. position: relative;
  548. display: inline-block;
  549. flex-shrink: 0;
  550. width: 40px;
  551. height: 24px;
  552. }
  553. .switch input {
  554. opacity: 0;
  555. width: 0;
  556. height: 0;
  557. }
  558. .slider {
  559. position: absolute;
  560. cursor: pointer;
  561. top: 0;
  562. left: 0;
  563. right: 0;
  564. bottom: 0;
  565. background-color: #ccc;
  566. transition: 0.2s;
  567. border-radius: 34px;
  568. }
  569. .slider:before {
  570. position: absolute;
  571. content: "";
  572. height: 16px;
  573. width: 16px;
  574. left: 4px;
  575. bottom: 4px;
  576. background-color: white;
  577. transition: 0.2s;
  578. border-radius: 50%;
  579. }
  580. input:checked + .slider {
  581. background-color: var(--primary-color);
  582. }
  583. input:focus + .slider {
  584. box-shadow: 0 0 1px var(--primary-color);
  585. }
  586. input:checked + .slider:before {
  587. transform: translateX(16px);
  588. }
  589. }
  590. &:focus {
  591. outline-color: var(--light-grey-3);
  592. }
  593. &:not(:last-of-type) {
  594. margin-bottom: 5px;
  595. }
  596. }
  597. }
  598. .tippy-content > div {
  599. display: flex;
  600. flex-direction: column;
  601. button {
  602. width: 150px;
  603. &:not(:last-of-type) {
  604. margin-bottom: 10px;
  605. }
  606. }
  607. }
  608. }
  609. .select {
  610. &:after {
  611. border-color: var(--primary-color);
  612. border-width: 1.5px;
  613. margin-top: -3px;
  614. }
  615. select {
  616. height: 36px;
  617. }
  618. }
  619. .button:focus,
  620. .button:active {
  621. border-color: var(--light-grey-2) !important;
  622. }
  623. .input:focus,
  624. .input:active,
  625. .textarea:focus,
  626. .textarea:active,
  627. .select select:focus,
  628. .select select:active {
  629. border-color: var(--primary-color) !important;
  630. }
  631. button.delete:focus {
  632. background-color: rgba(10, 10, 10, 0.3);
  633. }
  634. .tag {
  635. padding-right: 6px !important;
  636. }
  637. .button {
  638. &:hover,
  639. &:focus {
  640. filter: brightness(95%);
  641. }
  642. &.is-success {
  643. background-color: var(--green) !important;
  644. }
  645. &.is-primary {
  646. background-color: var(--primary-color) !important;
  647. }
  648. &.is-danger {
  649. background-color: var(--red) !important;
  650. }
  651. &.is-info {
  652. background-color: var(--primary-color) !important;
  653. }
  654. &.is-warning {
  655. background-color: var(--yellow) !important;
  656. }
  657. }
  658. .input,
  659. .button {
  660. height: 36px;
  661. }
  662. .fadein-helpbox-enter-active {
  663. transition-duration: 0.3s;
  664. transition-timing-function: ease-in;
  665. }
  666. .fadein-helpbox-leave-active {
  667. transition-duration: 0.3s;
  668. transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
  669. }
  670. .fadein-helpbox-enter-to,
  671. .fadein-helpbox-leave {
  672. max-height: 100px;
  673. overflow: hidden;
  674. }
  675. .fadein-helpbox-enter,
  676. .fadein-helpbox-leave-to {
  677. overflow: hidden;
  678. max-height: 0;
  679. }
  680. .control {
  681. margin-bottom: 5px !important;
  682. }
  683. .input-with-button {
  684. .control {
  685. margin-right: 0px !important;
  686. }
  687. input,
  688. select {
  689. width: 100%;
  690. height: 36px;
  691. border-radius: 3px 0 0 3px;
  692. border-right: 0;
  693. border-color: var(--light-grey-3);
  694. }
  695. .button {
  696. height: 36px;
  697. border-radius: 0 3px 3px 0;
  698. }
  699. }
  700. .page-title {
  701. margin: 0 0 50px 0;
  702. }
  703. .material-icons {
  704. user-select: none;
  705. -webkit-user-select: none;
  706. }
  707. .icon-with-button {
  708. margin-right: 3px;
  709. font-size: 18px;
  710. }
  711. .verified-song {
  712. font-size: 17px;
  713. color: var(--primary-color);
  714. }
  715. .section-title,
  716. h4.section-title {
  717. font-size: 26px;
  718. font-weight: 600;
  719. margin: 0px;
  720. }
  721. .section-description {
  722. font-size: 16px;
  723. font-weight: 400;
  724. margin-bottom: 10px !important;
  725. }
  726. .section-horizontal-rule {
  727. margin: 15px 0 30px 0;
  728. }
  729. .section-margin-bottom {
  730. height: 30px;
  731. }
  732. .margin-top-zero {
  733. margin-top: 0 !important;
  734. }
  735. .margin-bottom-zero {
  736. margin-bottom: 0 !important;
  737. }
  738. /** Universial items e.g. playlist items, queue items, activity items */
  739. .item-draggable {
  740. cursor: move;
  741. }
  742. .universal-item {
  743. display: flex;
  744. flex-direction: row;
  745. flex-grow: 1;
  746. align-items: center;
  747. justify-content: space-between;
  748. padding: 7.5px;
  749. border: 1px solid var(--light-grey-3);
  750. border-radius: 3px;
  751. overflow: hidden;
  752. .item-thumbnail {
  753. width: 65px;
  754. height: 65px;
  755. margin: -7.5px;
  756. border-radius: 3px 0 0 3px;
  757. }
  758. .item-title {
  759. font-size: 20px;
  760. overflow: hidden;
  761. text-overflow: ellipsis;
  762. white-space: nowrap;
  763. }
  764. .item-description {
  765. font-size: 14px;
  766. overflow: hidden;
  767. text-overflow: ellipsis;
  768. white-space: nowrap;
  769. }
  770. .universal-item-actions {
  771. display: flex;
  772. flex-direction: row;
  773. margin-left: 10px;
  774. justify-content: center;
  775. @media screen and (max-width: 800px) {
  776. flex-wrap: wrap;
  777. }
  778. .action-dropdown-icon {
  779. display: flex;
  780. color: var(--primary-color);
  781. }
  782. .song-actions {
  783. display: flex;
  784. }
  785. .button {
  786. width: 146px;
  787. }
  788. i {
  789. cursor: pointer;
  790. color: var(--dark-grey);
  791. &:hover,
  792. &:focus {
  793. filter: brightness(90%);
  794. }
  795. &:not(:first-of-type) {
  796. margin-left: 5px;
  797. }
  798. }
  799. .play-icon {
  800. color: var(--green);
  801. }
  802. .edit-icon,
  803. .view-icon,
  804. .add-to-playlist-icon {
  805. color: var(--primary-color);
  806. }
  807. .hide-icon {
  808. color: var(--light-grey-3);
  809. }
  810. .stop-icon,
  811. .delete-icon {
  812. color: var(--red);
  813. }
  814. .report-icon {
  815. color: var(--yellow);
  816. }
  817. }
  818. }
  819. .save-button-mixin {
  820. min-width: 200px;
  821. &:disabled {
  822. background-color: var(--light-grey) !important;
  823. color: var(--black);
  824. }
  825. }
  826. .save-button-transition-enter-active {
  827. transition: all 0.1s ease;
  828. }
  829. .save-button-transition-enter {
  830. transform: translateX(20px);
  831. opacity: 0;
  832. }
  833. .youtube-icon {
  834. margin-right: 3px;
  835. height: 20px;
  836. width: 20px;
  837. -webkit-mask: url("/assets/social/youtube.svg") no-repeat center;
  838. mask: url("/assets/social/youtube.svg") no-repeat center;
  839. background-color: var(--youtube);
  840. }
  841. #forgot-password {
  842. display: flex;
  843. justify-content: flex-start;
  844. margin: 5px 0;
  845. }
  846. .steps-fade-enter-active,
  847. .steps-fade-leave-active {
  848. transition: all 0.3s ease;
  849. }
  850. .steps-fade-enter,
  851. .steps-fade-leave-to {
  852. opacity: 0;
  853. }
  854. .skip-step {
  855. background-color: var(--grey-3);
  856. color: var(--white);
  857. }
  858. #steps {
  859. display: flex;
  860. align-items: center;
  861. justify-content: center;
  862. height: 50px;
  863. margin-top: 36px;
  864. @media screen and (max-width: 300px) {
  865. display: none;
  866. }
  867. .step {
  868. display: flex;
  869. align-items: center;
  870. justify-content: center;
  871. border-radius: 100%;
  872. border: 1px solid var(--dark-grey);
  873. min-width: 50px;
  874. min-height: 50px;
  875. background-color: var(--white);
  876. font-size: 30px;
  877. cursor: pointer;
  878. &.selected {
  879. background-color: var(--primary-color);
  880. color: var(--white) !important;
  881. border: 0;
  882. }
  883. }
  884. .divider {
  885. display: flex;
  886. justify-content: center;
  887. width: 180px;
  888. height: 1px;
  889. background-color: var(--dark-grey);
  890. }
  891. }
  892. .content-box {
  893. margin-top: 90px;
  894. border-radius: 3px;
  895. background-color: var(--white);
  896. border: 1px solid var(--dark-grey);
  897. max-width: 580px;
  898. padding: 40px;
  899. @media screen and (max-width: 300px) {
  900. margin-top: 30px;
  901. padding: 30px 20px;
  902. }
  903. }
  904. .content-box-optional-helper {
  905. margin-top: 15px;
  906. color: var(--primary-color);
  907. text-decoration: underline;
  908. font-size: 16px;
  909. a {
  910. color: var(--primary-color);
  911. }
  912. }
  913. .content-box-title {
  914. font-size: 25px;
  915. color: var(--black);
  916. }
  917. .content-box-description {
  918. font-size: 14px;
  919. color: var(--dark-grey);
  920. }
  921. .content-box-inputs {
  922. margin-top: 35px;
  923. .input-with-button {
  924. .button {
  925. width: 105px;
  926. }
  927. @media screen and (max-width: 450px) {
  928. flex-direction: column;
  929. }
  930. }
  931. label {
  932. font-size: 11px;
  933. }
  934. #change-password-button {
  935. margin-top: 36px;
  936. width: 175px;
  937. }
  938. }
  939. #password-visibility-container {
  940. display: flex;
  941. align-items: center;
  942. a {
  943. width: 0;
  944. margin-left: -30px;
  945. z-index: 0;
  946. top: 2px;
  947. position: relative;
  948. color: var(--light-grey-1);
  949. }
  950. }
  951. .news-item {
  952. font-family: "Karla";
  953. border-radius: 5px;
  954. padding: 20px;
  955. border: unset !important;
  956. box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
  957. * {
  958. font-family: Karla, Arial, sans-serif;
  959. font-size: 16px;
  960. }
  961. h1 {
  962. font-size: 40px;
  963. &:first-of-type {
  964. margin-top: 0;
  965. }
  966. }
  967. h2 {
  968. font-size: 30px;
  969. }
  970. h3 {
  971. font-size: 25px;
  972. }
  973. h4,
  974. h5,
  975. h6 {
  976. font-size: 20px;
  977. }
  978. h1,
  979. h2,
  980. h3,
  981. h4,
  982. h5,
  983. h6 {
  984. margin: 10px 0;
  985. }
  986. ul {
  987. list-style: unset;
  988. }
  989. li {
  990. margin-left: 30px;
  991. }
  992. blockquote {
  993. padding: 0px 15px;
  994. color: #6a737d;
  995. border-left: 0.25em solid #dfe2e5;
  996. }
  997. code {
  998. font-style: italic;
  999. }
  1000. }
  1001. </style>