From 3a88a638cf15b1a9f4910a51bd7a3bb64abe04b2 Mon Sep 17 00:00:00 2001 From: Ron Lucke Date: Thu, 30 Nov 2023 12:13:56 +0000 Subject: TIC #3388 Closes #3388 Merge request studip/studip!2340 --- package.json | 1 + .../stylesheets/scss/courseware/blocks/audio.scss | 352 +++++------ .../scss/courseware/blocks/default-block.scss | 19 + .../courseware/blocks/CoursewareAudioBlock.vue | 688 ++++++++++++++++----- .../vue/store/courseware/courseware.module.js | 17 + 5 files changed, 739 insertions(+), 338 deletions(-) diff --git a/package.json b/package.json index 3e8939b..ef5ea47 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "md5": "^2.3.0", "mini-css-extract-plugin": "1.3.1", "mitt": "2.1.0", + "mp3tag.js": "3.7.1", "multiselect": "0.9.12", "pdfjs-dist": "^2.6.347", "portal-vue": "^2.1.7", diff --git a/resources/assets/stylesheets/scss/courseware/blocks/audio.scss b/resources/assets/stylesheets/scss/courseware/blocks/audio.scss index c5c530e..2ea944b 100644 --- a/resources/assets/stylesheets/scss/courseware/blocks/audio.scss +++ b/resources/assets/stylesheets/scss/courseware/blocks/audio.scss @@ -1,231 +1,205 @@ -@use '../../../mixins.scss' as *; - -$media-buttons: ( - play: play, - stop: stop, - pause: pause, - prev: arr_eol-left, - next: arr_eol-right -); - .cw-block-audio { .cw-audio-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; border: solid thin var(--content-color-40); - padding-top: 1em; - } - .cw-audio-controls { - text-align: right; - padding: 0 0.5em; - } - .cw-audio-range { - margin: 0 5px 10px 0; - &::-moz-focus-outer { - border: 0; - } - &.ui-widget-content { - background-color: var(--base-color); - } - .ui-widget-header { - background-color: var(--dark-gray-color-5); - } - .ui-slider-handle { - border-radius: 20px; - width: 1em; - height: 1.7em; - top: -0.5em; - background-color: var(--dark-gray-color-20); - border-color: var(--content-color-40); - cursor: pointer; - margin-left: -2px; - } + padding: 36px; + gap: 64px; } - .cw-audio-button { - border: solid thin var(--content-color-40); - background-color: var(--white); - background-repeat: no-repeat; - background-position: center center; - background-size: 24px; - min-height: 27px; - line-height: 130%; - padding: 5px 15px 5px 30px; - cursor: pointer; - font-size: 14px; - box-sizing: border-box; - text-align: center; - text-decoration: none; - vertical-align: bottom; - white-space: nowrap; - min-width: unset; - margin: 5px; - height: 46px; - width: 46px; - display: inline-block; - - &:hover { - background-color: var(--base-color); - } - @each $button, $icon in $media-buttons { - &.cw-audio-#{$button}button { - @include background-icon($icon, clickable, 24); - &:hover { - @include background-icon($icon, info-alt, 24); - } - } + .cw-audio-recorder, + .cw-audio-player { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 36px; + flex-grow: 100; + + &.with-playlist { + flex-direction: column; } - } - .cw-audio-time { - position: relative; - top: -1em; - color: var(--base-gray); - } + .cw-audio-cover { + margin: 0 auto; + display: flex; + flex-direction: row; - .cw-audio-range { - display: block; - margin: 0 auto 1.5em; - -webkit-appearance: none; - position: relative; - overflow: hidden; - height: 18px; - width: 100%; - cursor: pointer; - border-radius: 0; - } + &.with-edit-button { + position: relative; + right: -8px; + } - .cw-audio-range::-webkit-slider-runnable-track { - background: var(--dark-gray-color-20); - } + .cover { + width: 256px; + height: 256px; + object-fit: cover; + } - .cw-audio-range::-webkit-slider-thumb { - -webkit-appearance: none; - width: 9px; /* 1 */ - height: 18px; - background: var(--white); - box-shadow: -100vw 0 0 100vw var(--base-color); - border: solid thin var(--content-color-40); - } + .default-cover { + padding: 64px; + border: solid thin var(--content-color-40); + } - .cw-audio-range::-moz-range-track { - height: 18px; - background: var(--dark-gray-color-10); - } + &.loading { + img { + visibility: hidden; + } + } - .cw-audio-range::-moz-range-thumb { - background: var(--white); - height: 18px; - width: 9px; - border: solid thin var(--content-color-40); - border-radius: 0 !important; - box-shadow: -100vw 0 0 100vw var(--base-color); - box-sizing: border-box; - } + button { + width: 16px; + height: 16px; + cursor: pointer; + padding: 0 8px; + background-color: transparent; + border: none; + } + } - .cw-audio-range::-ms-fill-lower { - background: var(--base-color); - } + .cw-audio-controls-wrapper { + flex-grow: 1; + min-width: 256px; + text-align: center; + display: flex; + flex-direction: column; + + .cw-audio-current-track { + flex-grow: 1; + max-width: 270px; + min-height: 60px; + margin: 0 auto; + + h2, + h3 { + margin-top: 0; + } + } - .cw-audio-range::-ms-thumb { - background: var(--white); - border: solid thin var(--content-color-40); - height: 18px; - width: 9px; - box-sizing: border-box; - } + .cw-audio-controls { + .cw-audio-progress { + .cw-audio-range { + width: 100%; + -webkit-appearance: none; + appearance: none; + cursor: pointer; + outline: none; + height: 2px; + background: var(--content-color-40); + + &::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + height: 16px; + width: 16px; + background-color: var(--base-color); + border-radius: 50%; + border: none; + } - .cw-audio-range::-ms-ticks-after { - display: none; - } + &::-moz-range-thumb { + height: 16px; + width: 16px; + background-color: var(--base-color); + border-radius: 50%; + border: none; + } + } - .cw-audio-range::-ms-ticks-before { - display: none; - } + .cw-audio-time { + display: flex; + flex-direction: row; + justify-content: space-between; + } + } - .cw-audio-range::-ms-track { - background: var(--dark-gray-color-20); - color: transparent; - height: 18px; - border: none; + .cw-recorder-visualization { + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 2px; + height: 28px; + margin-bottom: 1em; + padding-bottom: 4px; + border-bottom: solid 2px var(--content-color-40); + + .cw-recorder-visualization-bar { + min-height: 4px; + width: calc(100% / 32); + background-color: var(--base-color); + + &.idle-bar { + height: 4px !important; + } + } + } + .cw-audio-buttons { + display: flex; + flex-direction: row; + justify-content: space-evenly; + + button { + cursor: pointer; + border: none; + background: transparent; + } + } + } + } } - .cw-audio-range::-ms-tooltip { - display: none; - } .cw-audio-playlist-wrapper { - margin-top: -1em; - padding-top: 1em; - border: solid thin var(--content-color-40); - border-top: none; - - &.empty { - border: none; - } + flex-grow: 1; + min-width: 270px; + max-height: 450px; + overflow-y: auto; .cw-audio-playlist { padding-left: 0; + margin-top: -1em; list-style: none; cursor: pointer; - &.with-recorder { - border-bottom: solid thin var(--content-color-40); - } - li { - margin: 0 1em; &:not(:last-child) { border-bottom: solid thin var(--dark-gray-color-30); } .cw-playlist-item { display: block; - @include background-icon(file-audio2, clickable, 24); - background-repeat: no-repeat; - background-position: 1em center; - - margin: 1em 0; - padding: 1em; - padding-left: 4em; - color: var(--base-color); - &:hover { - color: var(--active-color); - } - &.current-item { - @include background-icon(play, clickable, 24); - font-weight: 700; - &.is-playing { - @include background-icon(pause, clickable, 24); - } + padding: 1em 0; + margin: 0; + img { + vertical-align: middle; } } } } - .cw-audio-playlist-recorder { - padding: 1em; - } } - - .cw-audio-current-track { - @include background-icon(file-audio2, info, 96); - background-position: top center; - background-repeat: no-repeat; - width: 100%; - min-height: 140px; - margin: 1em 0 2em 0; - p { - text-align: center; - padding-top: 106px; +} +.edit-mp3-cover-wrapper { + display: flex; + flex-direction: row; + margin-bottom: 1em; + + .edit-mp3-cover { + width: 128px; + height: 128px; + object-fit: cover; + + &.default-cover { + padding: 32px; + border: solid thin var(--content-color-40); } } - .cw-audio-empty { - @include background-icon(file, info, 96); - border: solid thin var(--content-color-40); - background-position: center 1em; - background-repeat: no-repeat; - min-height: 140px; - padding: 1em; - p { - text-align: center; - padding-top: 106px; - } + + .remove-cover { + background-color: transparent; + border: none; + height: 16px; + width: 16px; + padding: 0 8px; + cursor: pointer; } } diff --git a/resources/assets/stylesheets/scss/courseware/blocks/default-block.scss b/resources/assets/stylesheets/scss/courseware/blocks/default-block.scss index 24c5751..21e583e 100644 --- a/resources/assets/stylesheets/scss/courseware/blocks/default-block.scss +++ b/resources/assets/stylesheets/scss/courseware/blocks/default-block.scss @@ -131,4 +131,23 @@ text-align: center; padding-top: 106px; } +} + +.cw-call-to-action { + border: solid thin var(--content-color-40); + border-top: none; + + button { + width: 100%; + background-color: var(--activity-color-20); + border: none; + text-align: left; + padding: 1em; + cursor: pointer; + + img { + margin: 0 1em; + vertical-align: middle; + } + } } \ No newline at end of file diff --git a/resources/vue/components/courseware/blocks/CoursewareAudioBlock.vue b/resources/vue/components/courseware/blocks/CoursewareAudioBlock.vue index e346d20..9ca52b0 100644 --- a/resources/vue/components/courseware/blocks/CoursewareAudioBlock.vue +++ b/resources/vue/components/courseware/blocks/CoursewareAudioBlock.vue @@ -19,106 +19,260 @@ @durationchange="setDuration" @ended="onEndedListener" /> -
-
-

{{ activeTrackName }}

+
+
+
+ + + +
+
+
+

{{ trackTitle }}

+

{{ trackArtist }}

+
+
+
+ +
+
+
+ + + + +
+
+
-
- - {{ currentTime }} {{ durationTime ? '/ ' + durationTime : '' }} - - + + + + +
+
+
- -
-

{{ $gettext('Es ist keine Audio-Datei verfügbar') }}

-
-
- -
- - - - - - - - {{ $gettext('Aufnahme läuft') }}: {{seconds2time(timer)}} - +
+
+
+ + +
+ + +