Add deletion control for attached videos

0fa1b26fa44de4c4f1182cd9182426f8580e7d6b

Cohee <18619528+Cohee1207@users.noreply.github.com>

4 files changed, +74 -33Ignore whitespace
public/index.html+23 -13
@@ -6844,19 +6844,19 @@
68446844 <div class="mes_reasoning"></div>
68456845 </details>
68466846 <div class="mes_text"></div>
68476847 <div class="mes_img_container">
68486848 <div class="mes_img_controls">
68496849 <div title="Expand and zoom" class="right_menu_button fa-lg fa-solid fa-magnifying-glass mes_img_enlarge" data-i18n="[title]Expand and zoom"></div>
68506850 <div title="Caption" class="right_menu_button fa-lg fa-solid fa-envelope-open-text mes_img_caption" data-i18n="[title]Caption"></div>
68516851 <div title="Delete" class="right_menu_button fa-lg fa-solid fa-trash-can mes_img_delete" data-i18n="[title]Delete"></div>
68526852 </div>
68536853 <div class="mes_img_swipes">
68546854 <div title="Swipe left" class="right_menu_button fa-lg fa-solid fa-chevron-left mes_img_swipe_left" data-i18n="[title]Swipe left"></div>
68556855 <div class="mes_img_swipe_counter">1/1</div>
68566856 <div title="Swipe right" class="right_menu_button fa-lg fa-solid fa-chevron-right mes_img_swipe_right" data-i18n="[title]Swipe right"></div>
68576857 </div>
68586858 <img class="mes_img" src="" />
68596859 </div>
68606860 <div class="mes_bias"></div>
68616861 </div>
68626862 <div class="flex-container swipeRightBlock flexFlowColumn flexNoGap">
@@ -7066,6 +7066,16 @@
70667066 <div class="right_menu_button mes_file_delete fa-solid fa-trash-can" title="Remove the file" data-i18n="[title]Remove the file"></div>
70677067 </div>
70687068 </div>
7069+
7070+ <div id="message_video_template" class="template_element">
7071+ <div class="mes_video_container">
7072+ <div class="mes_video_controls">
7073+ <div><!-- Placeholder --></div>
7074+ <div title="Delete" class="right_menu_button fa-lg fa-solid fa-trash-can mes_video_delete" data-i18n="[title]Delete"></div>
7075+ </div>
7076+ <video class="mes_video" controls preload="metadata"></video>
7077+ </div>
7078+ </div>
70697079 </div>
70707080 <div id="movingDivs">
70717081 <div id="floatingPrompt" class="drawer-content flexGap5">
public/script.js+5 -10
@@ -2505,16 +2505,11 @@ export function appendMediaToMessage(mes, messageElement, adjustScroll = true) {
25052505
25062506 // Add video to message
25072507 if (mes.extra?.video) {
25082508 const container = messageElement.find$('#message_video_template .mes_blockmes_video_container').clone();
2509+ messageElement.find('.mes_video_container').remove();
2510+ messageElement.find('.mes_block').append(container);
25092511 const chatHeight = $('#chat').prop('scrollHeight');
2510-
2512+ const video = container.find('.mes_video');
2511- // Create video element if it doesn't exist
2512- let video = messageElement.find('.mes_video');
2513- if (video.length === 0) {
2514- video = $('<video class="mes_video" controls preload="metadata"></video>');
2515- container.append(video);
2516- }
2517-
25182513 video.off('loadedmetadata').on('loadedmetadata', function () {
25192514 if (!adjustScroll) {
25202515 return;
@@ -2527,7 +2522,7 @@ export function appendMediaToMessage(mes, messageElement, adjustScroll = true) {
25272522
25282523 video.attr('src', mes.extra?.video);
25292524 } else {
25302525 messageElement.find('.mes_videomes_video_container').remove();
25312526 }
25322527
25332528 // Add file to message
public/scripts/chats.js+22 -0
@@ -893,6 +893,27 @@ async function deleteMessageImage() {
893893 await saveChatConditional();
894894}
895895
896+async function deleteMessageVideo() {
897+ const confirm = await Popup.show.confirm(t`Delete video from message?`, t`This action can't be undone.`);
898+ if (!confirm) {
899+ return;
900+ }
901+
902+ const mesBlock = $(this).closest('.mes');
903+ const mesId = mesBlock.attr('mesid');
904+ const message = chat[mesId];
905+
906+ if (!message?.extra?.video) {
907+ console.warn('Message has no video or it is empty');
908+ return;
909+ }
910+
911+ delete message.extra.video;
912+ mesBlock.find('.mes_video_container').remove();
913+
914+ await saveChatConditional();
915+}
916+
896917/**
897918 * Deletes file from the server.
898919 * @param {string} url Path to the file on the server
@@ -1856,6 +1877,7 @@ export function initChatUtilities() {
18561877 $(document).on('click', '.mes_img', expandMessageImage);
18571878 $(document).on('click', '.mes_img_enlarge', expandAndZoomMessageImage);
18581879 $(document).on('click', '.mes_img_delete', deleteMessageImage);
1880+ $(document).on('click', '.mes_video_delete', deleteMessageVideo);
18591881
18601882 $('#file_form_input').on('change', async () => {
18611883 const fileInput = document.getElementById('file_form_input');
public/style.css+24 -10
@@ -5033,8 +5033,9 @@ a:hover {
50335033 display: none;
50345034}
50355035
50365036/* Message images/video */
50375037.mes .mes_img_container {,
5038+.mes .mes_video_container {
50385039 max-width: 100%;
50395040 /*to fit inside single window height of mobile landscape*/
50405041 display: none;
@@ -5044,8 +5045,12 @@ a:hover {
50445045 padding: 0.5rem;
50455046}
50465047
5048+.mes .mes_video_container:has(.mes_video[src]) {
5049+ display: flex;
5050+}
5051+
50475052.mes_img {
50485053 border-radius: 10px5px;
50495054 max-width: 100%;
50505055 max-height: 40vh;
50515056 image-rendering: -webkit-optimize-contrast;
@@ -5059,7 +5064,8 @@ a:hover {
50595064}
50605065
50615066.mes_img_swipes,
50625067.mes_img_controls {,
5068+.mes_video_controls {
50635069 position: absolute;
50645070 top: 0.1em;
50655071 left: 0;
@@ -5070,6 +5076,8 @@ a:hover {
50705076 justify-content: space-between;
50715077 align-items: center;
50725078 padding: 1em;
5079+ z-index: 1;
5080+ transition: opacity var(--animation-duration) ease-in-out;
50735081}
50745082
50755083.mes_img_swipes {
@@ -5078,7 +5086,8 @@ a:hover {
50785086}
50795087
50805088.mes_img_swipes .right_menu_button,
50815089.mes_img_controls .right_menu_button {,
5090+.mes_video_controls .right_menu_button {
50825091 filter: brightness(90%);
50835092 text-shadow: 1px 1px var(--SmartThemeShadowColor) !important;
50845093 padding: 1px;
@@ -5087,23 +5096,29 @@ a:hover {
50875096}
50885097
50895098.mes_img_swipes .right_menu_button::before,
50905099.mes_img_controls .right_menu_button::before {,
5100+.mes_video_controls .right_menu_button::before {
50915101 /* Fix weird alignment with this font-awesome icons on focus */
50925102 position: relative;
50935103 top: 0.6125em;
50945104}
50955105
50965106.mes_img_swipes .right_menu_button:hover,
50975107.mes_img_controls .right_menu_button:hover {,
5108+.mes_video_controls .right_menu_button:hover {
50985109 filter: brightness(150%);
50995110}
51005111
5112+/* It's better to show controls only when the video is not playing */
5113+/* but :playing pseudo-class is not supported in all browsers */
5114+/* .mes_video_container:focus-within .mes_video_controls:not(:has(.mes_video:playing)), */
51015115.mes_img_container:has(.mes_img.error) .mes_img_swipes,
51025116.mes_img_container:has(.mes_img.error) .mes_img_controls,
51035117.mes_img_container:hover .mes_img_swipes,
51045118.mes_img_container:focus-within .mes_img_swipes,
51055119.mes_img_container:hover .mes_img_controls,
51065120.mes_img_container:focus-within .mes_img_controls {,
5121+.mes_video_container:hover .mes_video_controls {
51075122 opacity: 1;
51085123}
51095124
@@ -5203,9 +5218,8 @@ body:not(.sd) .mes_img_swipes {
52035218.mes_video {
52045219 max-width: 100%;
52055220 max-height: 400px;
52065221 border-radius: 8px5px;
52075222 background: #000;
5208- margin: 0.5rem;
52095223}
52105224
52115225/* Ensure video controls are visible */