diff --git a/files/style/be.bastelstu.chat.scss b/files/style/be.bastelstu.chat.scss index 0d0a4a2..331cc93 100644 --- a/files/style/be.bastelstu.chat.scss +++ b/files/style/be.bastelstu.chat.scss @@ -1,10 +1,10 @@ /* - * Copyright (c) 2010-2021 Tim Düsterhus. + * Copyright (c) 2010-2022 Tim Düsterhus. * * Use of this software is governed by the Business Source License * included in the LICENSE file. * - * Change Date: 2026-03-10 + * Change Date: 2026-08-10 * * On the date above, in accordance with the Business Source * License, use of this software will be governed by version 2 @@ -70,17 +70,31 @@ #tpl_chat_log { flex: 0.5 0 auto; flex-direction: column; margin-left: 10px; - max-width: 310px; + max-width: min(310px, 35%); > .boxContainer { -webkit-columns: 1; -moz-columns: 1; columns: 1; + + margin-bottom: 0; + + > .box { + border-bottom: none; + } } } } - @include screen-lg { + @include screen-sm-up { + .layoutBoundary { + flex-wrap: nowrap; + } + + .content + .sidebar.boxesSidebarRight { + margin-top: 0; + } + .boxesSidebarRight { &, > .boxContainer { @@ -89,6 +103,7 @@ #tpl_chat_log { } > .boxContainer { + overflow: auto; flex: 1 1 auto; > .box { @@ -96,15 +111,27 @@ #tpl_chat_log { flex: 2 0 0px; min-height: 15rem; + html.fullscreen & { + flex: 1 1 content; + } + > .boxContent { flex-basis: 6rem; } } &[data-box-identifier='be.bastelstu.chat.roomListSidebar'] { - flex: 1 1 0px; + flex: 1 1 12rem; min-height: 12rem; + html.fullscreen & { + flex: 1 1 content; + } + + @media screen and (max-height: 440px) { + min-height: 120px; + } + .badge { float: right; padding-left: 7px; @@ -128,7 +155,9 @@ #tpl_chat_log { } } } + } + @include screen-lg { #chatQuickSettings { display: none; } @@ -157,6 +186,11 @@ #tpl_chat_log { flex-direction: column; flex: 1 1 auto; width: 100%; + + > .contentInteraction:first-child { + margin-top: 0; + margin-bottom: 20px; + } } #chatMessageStream > .scrollContainer, @@ -257,7 +291,8 @@ #tpl_chat_log { // Limit embedded images and videos to a reasonable size img:not(.smiley):not(.userAvatarImage) { - max-width: $chatEmbedMaxWidth; + // Workaround: `min` is an internal Sass function but we want the actual CSS function + max-width: min + unquote( '(' ) + "#{100%, $chatEmbedMaxWidth}" + unquote( ')' ); } .videoContainer { @@ -371,15 +406,18 @@ #tpl_chat_log { #chatInputContainer { margin-top: 10px; + margin-bottom: 1.48 * $wcfFontSizeDefault; // 1.48 is the default line height clear: both; - textarea { - resize: none; - } .charCounter { float: right; color: $wcfContentDimmedText; + margin-bottom: -(1.48 * $wcfFontSizeDefault); + } + + textarea { + resize: none; } > div { @@ -489,30 +527,21 @@ #tpl_chat_log { margin-left: 5px; } - #smileyPickerContainer { - #smilies-text { - @if variable_exists(wcfContentContainerBackground) { - background-color: $wcfContentContainerBackground; - } @else { - // Compatibility with API_VERSION 3.0 - background-color: rgba(255, 255, 255, 1); - } + #chatUserList, + [data-box-identifier='be.bastelstu.chat.roomListSidebar'] { + .modalCloseButton { + margin: 0 -10px -20px -10px; + } + } - border: 1px solid $wcfContentBorderInner; - padding: 20px; - margin-top: 20px; - margin-bottom: 20px; - - > .smileyList { - overflow: auto; - } + @include screen-md-down { + #smileyPickerContainer[data-show='true'] > div { + margin: 0; } - #smileyPickerCloseButton { - display: none; - } - - @include screen-md-down { + #smileyPickerContainer, + #chatUserList, + [data-box-identifier='be.bastelstu.chat.roomListSidebar'] { &[data-show='true'] { position: fixed; top: 0; @@ -524,7 +553,10 @@ #tpl_chat_log { flex-direction: column; pointer-events: all; - #smileyPickerCloseButton { + background-color: $wcfContentBackground; + + .modalCloseButton { + border-top: 1px solid $wcfContentBorderInner; background-color: $wcfSidebarBackground; color: $wcfSidebarLink; display: block; @@ -534,12 +566,9 @@ #tpl_chat_log { cursor: pointer; } - #smilies-text { - border-top: none; - border-right: none; - border-left: none; + > div { + border: none; - margin: 0; height: 0; flex: 1 1 auto; position: relative; @@ -570,6 +599,24 @@ #tpl_chat_log { } } + #smileyPickerContainer { + > .messageTabMenuContent { + background-color: $wcfContentContainerBackground; + border: 1px solid $wcfContentBorderInner; + padding: 20px; + margin-top: 20px; + margin-bottom: 20px; + + > .smileyList { + overflow: auto; + } + } + + .modalCloseButton { + display: none; + } + } + #chatAttachmentUploadDialog { .attachmentPreview { text-align: center; @@ -607,7 +654,9 @@ html.fullscreen { .pageHeaderContainer, .pageNavigation, - .pageFooter { + .boxesFooterBoxes, + .pageFooter, + .contentInteraction { display: none; } diff --git a/files_wcf/js/Bastelstu.be/Chat/Helper.js b/files_wcf/js/Bastelstu.be/Chat/Helper.js index 392f1c3..97edbd2 100644 --- a/files_wcf/js/Bastelstu.be/Chat/Helper.js +++ b/files_wcf/js/Bastelstu.be/Chat/Helper.js @@ -1,10 +1,10 @@ /* - * Copyright (c) 2010-2021 Tim Düsterhus. + * Copyright (c) 2010-2022 Tim Düsterhus. * * Use of this software is governed by the Business Source License * included in the LICENSE file. * - * Change Date: 2026-03-10 + * Change Date: 2026-08-10 * * On the date above, in accordance with the Business Source * License, use of this software will be governed by version 2 @@ -135,6 +135,7 @@ define(['WoltLabSuite/Core/Date/Util', 'WoltLabSuite/Core/Language'], function ( textarea.parentNode.classList.add('flexibleTextarea') } + textarea.removeAttribute('rows') textarea.classList.add('flexibleTextareaContent') pre.classList.add('flexibleTextareaMirror') @@ -377,6 +378,20 @@ define(['WoltLabSuite/Core/Date/Util', 'WoltLabSuite/Core/Language'], function ( return out } + + static getElementSiblings(element) { + if (!element || !element.parentNode) { + return + } + + const children = [ ...element.parentNode.children ] + const index = children.indexOf(element); + + return [ + ...children.slice(0, index), + ...children.slice(index + 1) + ] + } } return Helper diff --git a/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/RoomListButton.js b/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/RoomListButton.js new file mode 100644 index 0000000..784ef40 --- /dev/null +++ b/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/RoomListButton.js @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2010-2022 Tim Düsterhus. + * + * Use of this software is governed by the Business Source License + * included in the LICENSE file. + * + * Change Date: 2026-08-10 + * + * On the date above, in accordance with the Business Source + * License, use of this software will be governed by version 2 + * or later of the General Public License. + */ + +define([ + '../../Helper', + './Button', + 'WoltLabSuite/Core/Dom/Util', + 'WoltLabSuite/Core/Language', + 'WoltLabSuite/Core/Ui/Screen' +], function ( + Helper, + Button, + DomUtil, + Language, + UiScreen +) { + 'use strict' + + const DEPENDENCIES = [].concat(Button.DEPENDENCIES || []) + class RoomListButton extends Button { + constructor(element, ...superDeps) { + super(element, ...superDeps) + + this.roomList = document.querySelector(`[data-box-identifier='be.bastelstu.chat.roomListSidebar']`) + if (!this.roomList) { + element.remove() + return + } + + this.mobile = false + this.open = false + this.sidebar = document.querySelector('.sidebar') + + UiScreen.on('screen-xs', { + match: () => this.enableMobile(), + unmatch: () => this.disableMobile(), + setup: () => this.enableMobile(), + }) + } + + enableMobile() { + this.mobile = true + this.element.parentElement.hidden = false + } + + disableMobile() { + if (this.open) { + this.show(false) + } + + this.element.parentElement.hidden = true + this.mobile = false + } + + show(doShow = true) { + if (doShow) { + this.open = true + this.sidebar.style.setProperty('display', 'contents', ''); + + for (let sibling of Helper.getElementSiblings(this.roomList)) { + DomUtil.hide(sibling) + } + + this.closeButton = document.createElement('span') + this.closeButton.classList.add('modalCloseButton') + this.closeButton.innerText = Language.get('wcf.global.button.close') + this.closeButton.addEventListener('click', () => this.show(false)) + this.roomList.appendChild(this.closeButton) + + this.roomList.dataset.show = 'true' + + if (this.mobile) { + UiScreen.scrollDisable() + } + } + else { + delete this.roomList.dataset.show + this.closeButton.remove() + + for (let sibling of Helper.getElementSiblings(this.roomList)) { + DomUtil.show(sibling) + } + + this.sidebar.style.removeProperty('display') + this.open = false + + if (this.mobile) { + UiScreen.scrollEnable() + } + } + } + + async onClick(event) { + super.onClick(event) + + this.show(!this.open) + } + } + RoomListButton.DEPENDENCIES = DEPENDENCIES + + return RoomListButton +}) diff --git a/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/SmiliesButton.js b/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/SmiliesButton.js index e2f1a20..c58280a 100644 --- a/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/SmiliesButton.js +++ b/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/SmiliesButton.js @@ -1,10 +1,10 @@ /* - * Copyright (c) 2010-2021 Tim Düsterhus. + * Copyright (c) 2010-2022 Tim Düsterhus. * * Use of this software is governed by the Business Source License * included in the LICENSE file. * - * Change Date: 2026-03-10 + * Change Date: 2026-08-10 * * On the date above, in accordance with the Business Source * License, use of this software will be governed by version 2 @@ -97,7 +97,7 @@ define(['./ToggleButton', 'WoltLabSuite/Core/Ui/Screen'], function ( enableMobile() { this.mobile = true - elHide(this.element) + elHide(this.element.parentElement) elShow(this.shadowToggleButton) // Do not show the overlay when the viewport changes @@ -114,7 +114,7 @@ define(['./ToggleButton', 'WoltLabSuite/Core/Ui/Screen'], function ( disableMobile() { this.mobile = false - elShow(this.element) + elShow(this.element.parentElement) elHide(this.shadowToggleButton) UiScreen.scrollEnable() diff --git a/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/UserListButton.js b/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/UserListButton.js new file mode 100644 index 0000000..cf7cb42 --- /dev/null +++ b/files_wcf/js/Bastelstu.be/Chat/Ui/Settings/UserListButton.js @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010-2022 Tim Düsterhus. + * + * Use of this software is governed by the Business Source License + * included in the LICENSE file. + * + * Change Date: 2026-08-10 + * + * On the date above, in accordance with the Business Source + * License, use of this software will be governed by version 2 + * or later of the General Public License. + */ + +define([ + '../../Helper', + './Button', + 'WoltLabSuite/Core/Dom/Util', + 'WoltLabSuite/Core/Language', + 'WoltLabSuite/Core/Ui/Screen' +], function ( + Helper, + Button, + DomUtil, + Language, + UiScreen +) { + 'use strict' + + const DEPENDENCIES = [].concat(Button.DEPENDENCIES || []) + class UserListButton extends Button { + constructor(element, ...superDeps) { + super(element, ...superDeps) + + this.mobile = false + this.open = false + this.userList = document.getElementById('chatUserList') + this.sidebar = document.querySelector('.sidebar') + + UiScreen.on('screen-xs', { + match: () => this.enableMobile(), + unmatch: () => this.disableMobile(), + setup: () => this.enableMobile(), + }) + } + + enableMobile() { + this.mobile = true + this.element.parentElement.hidden = false + } + + disableMobile() { + if (this.open) { + this.show(false) + } + + this.element.parentElement.hidden = true + this.mobile = false + } + + show(doShow = true) { + if (doShow) { + this.open = true + this.sidebar.style.setProperty('display', 'contents', ''); + + for (let sibling of Helper.getElementSiblings(this.userList)) { + DomUtil.hide(sibling) + } + + this.closeButton = document.createElement('span') + this.closeButton.classList.add('modalCloseButton') + this.closeButton.innerText = Language.get('wcf.global.button.close') + this.closeButton.addEventListener('click', () => this.show(false)) + this.userList.appendChild(this.closeButton) + + this.userList.dataset.show = 'true' + + if (this.mobile) { + UiScreen.scrollDisable() + } + } + else { + delete this.userList.dataset.show + this.closeButton.remove() + + for (let sibling of Helper.getElementSiblings(this.userList)) { + DomUtil.show(sibling) + } + + this.sidebar.style.removeProperty('display') + this.open = false + + if (this.mobile) { + UiScreen.scrollEnable() + } + } + } + + async onClick(event) { + super.onClick(event) + + this.show(!this.open) + } + } + UserListButton.DEPENDENCIES = DEPENDENCIES + + return UserListButton +}) diff --git a/language/de.xml b/language/de.xml index 090c6a8..c0fa35b 100644 --- a/language/de.xml +++ b/language/de.xml @@ -124,6 +124,8 @@ + + diff --git a/language/en.xml b/language/en.xml index b9bf422..8a865b9 100644 --- a/language/en.xml +++ b/language/en.xml @@ -124,6 +124,8 @@ + + diff --git a/templates/quickSettings.tpl b/templates/quickSettings.tpl index 83da260..033fcc7 100644 --- a/templates/quickSettings.tpl +++ b/templates/quickSettings.tpl @@ -4,6 +4,8 @@
  • {lang}chat.room.button.fullscreen{/lang}
  • {lang}chat.room.button.notifications{/lang}
  • {lang}chat.room.button.autoscroll{/lang}
  • + + {event name='buttons'} diff --git a/templates/room.tpl b/templates/room.tpl index b801d06..48e6316 100644 --- a/templates/room.tpl +++ b/templates/room.tpl @@ -10,19 +10,16 @@ {/capture} -{capture assign='headerNavigation'} +{capture assign='contentInteractionButtons'} {if $room->canSeeLog()} -
  • - - - -
  • - {/if} -
  • - - + + {lang}chat.log.title{/lang} -
  • + {/if} + + + {lang}chat.room.button.leave{/lang} + {/capture} {capture assign='__pageDataAttributes'}data-room-id="{@$room->roomID}"{/capture} @@ -63,7 +60,7 @@ {/if}
    - + diff --git a/templates/smileyPicker.tpl b/templates/smileyPicker.tpl index f1d70e1..a68eb0b 100644 --- a/templates/smileyPicker.tpl +++ b/templates/smileyPicker.tpl @@ -1,6 +1,6 @@ {if MODULE_SMILEY && !$smileyCategories|empty} {/if} \ No newline at end of file