2
0
Эх сурвалжийг харах

Use `flex-direction: column-reverse`

On the `<converse-chat-content>` element. This removes the need for all
the manual scrolling.

Firefox finally supports this feature. Unfortunately Firefox ESR doesn't
yet, but I can't wait anymore.
JC Brand 4 жил өмнө
parent
commit
825e2643ae

+ 0 - 7
src/plugins/chatview/styles/chatbox.scss

@@ -138,13 +138,6 @@
             flex-direction: column;
             flex-direction: column;
             justify-content: space-between;
             justify-content: space-between;
 
 
-            converse-chat-content {
-                display: flex;
-                flex-direction: column;
-                height: 100%;
-                justify-content: space-between;
-            }
-
             converse-chat-message {
             converse-chat-message {
                 .spinner {
                 .spinner {
                     width: 100%;
                     width: 100%;

+ 0 - 1
src/plugins/chatview/view.js

@@ -75,7 +75,6 @@ export default class ChatView extends BaseChatView {
 
 
     afterShown () {
     afterShown () {
         this.model.setChatState(_converse.ACTIVE);
         this.model.setChatState(_converse.ACTIVE);
-        this.scrollDown();
         this.maybeFocus();
         this.maybeFocus();
     }
     }
 }
 }

+ 0 - 1
src/plugins/headlines-view/view.js

@@ -25,7 +25,6 @@ class HeadlinesView extends BaseChatView {
 
 
         await this.model.messages.fetched;
         await this.model.messages.fetched;
         this.model.maybeShow();
         this.model.maybeShow();
-        this.scrollDown();
         /**
         /**
          * Triggered once the {@link _converse.HeadlinesBoxView} has been initialized
          * Triggered once the {@link _converse.HeadlinesBoxView} has been initialized
          * @event _converse#headlinesBoxViewInitialized
          * @event _converse#headlinesBoxViewInitialized

+ 0 - 14
src/plugins/muc-views/muc.js

@@ -21,15 +21,12 @@ export default class MUCView extends BaseChatView {
 
 
         this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged);
         this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged);
         this.listenTo(this.model, 'change:composing_spoiler', this.requestUpdateMessageForm);
         this.listenTo(this.model, 'change:composing_spoiler', this.requestUpdateMessageForm);
-        this.listenTo(this.model, 'change:hidden', () => this.afterShown());
-        this.listenTo(this.model, 'change:minimized', () => this.afterShown());
         this.listenTo(this.model, 'show', this.show);
         this.listenTo(this.model, 'show', this.show);
         this.listenTo(this.model.session, 'change:connection_status', this.updateAfterTransition);
         this.listenTo(this.model.session, 'change:connection_status', this.updateAfterTransition);
         this.listenTo(this.model.session, 'change:view', this.requestUpdate);
         this.listenTo(this.model.session, 'change:view', this.requestUpdate);
 
 
         this.updateAfterTransition();
         this.updateAfterTransition();
         this.model.maybeShow();
         this.model.maybeShow();
-        this.scrollDown();
         /**
         /**
          * Triggered once a { @link _converse.ChatRoomView } has been opened
          * Triggered once a { @link _converse.ChatRoomView } has been opened
          * @event _converse#chatRoomViewInitialized
          * @event _converse#chatRoomViewInitialized
@@ -43,17 +40,6 @@ export default class MUCView extends BaseChatView {
         return tpl_muc({ 'model': this.model });
         return tpl_muc({ 'model': this.model });
     }
     }
 
 
-    /**
-     * Callback method that gets called after the chat has become visible.
-     * @private
-     * @method _converse.ChatRoomView#afterShown
-     */
-    afterShown () {
-        if (!this.model.get('hidden') && !this.model.get('minimized')) {
-            this.scrollDown();
-        }
-    }
-
     /**
     /**
      * Closes this chat, which implies leaving the MUC as well.
      * Closes this chat, which implies leaving the MUC as well.
      * @private
      * @private

+ 16 - 61
src/shared/chat/chat-content.js

@@ -6,6 +6,8 @@ import { html } from 'lit';
 import { onScrolledDown } from './utils.js';
 import { onScrolledDown } from './utils.js';
 import { safeSave } from '@converse/headless/utils/core.js';
 import { safeSave } from '@converse/headless/utils/core.js';
 
 
+import './styles/chat-content.scss';
+
 
 
 export default class ChatContent extends CustomElement {
 export default class ChatContent extends CustomElement {
 
 
@@ -17,12 +19,11 @@ export default class ChatContent extends CustomElement {
 
 
     connectedCallback () {
     connectedCallback () {
         super.connectedCallback();
         super.connectedCallback();
-        this.debouncedMaintainScroll = debounce(this.maintainScrollPosition, 100);
         this.markScrolled = debounce(this._markScrolled, 50);
         this.markScrolled = debounce(this._markScrolled, 50);
 
 
         this.model = _converse.chatboxes.get(this.jid);
         this.model = _converse.chatboxes.get(this.jid);
         this.listenTo(this.model, 'change:hidden_occupants', this.requestUpdate);
         this.listenTo(this.model, 'change:hidden_occupants', this.requestUpdate);
-        this.listenTo(this.model, 'change:scrolled', this.requestUpdate);
+        this.listenTo(this.model, 'change:scrolled', this.scrollDown);
         this.listenTo(this.model.messages, 'add', this.requestUpdate);
         this.listenTo(this.model.messages, 'add', this.requestUpdate);
         this.listenTo(this.model.messages, 'change', this.requestUpdate);
         this.listenTo(this.model.messages, 'change', this.requestUpdate);
         this.listenTo(this.model.messages, 'remove', this.requestUpdate);
         this.listenTo(this.model.messages, 'remove', this.requestUpdate);
@@ -34,55 +35,22 @@ export default class ChatContent extends CustomElement {
         if (this.model.occupants) {
         if (this.model.occupants) {
             this.listenTo(this.model.occupants, 'change', this.requestUpdate);
             this.listenTo(this.model.occupants, 'change', this.requestUpdate);
         }
         }
-        // We jot down whether we were scrolled down before rendering, because when an
-        // image loads, it triggers 'scroll' and the chat will be marked as scrolled,
-        // which is technically true, but not what we want because the user
-        // didn't initiate the scrolling.
-        this.was_scrolled_up = this.model.get('scrolled');
-        this.addEventListener('imageLoaded', () => {
-            this.debouncedMaintainScroll();
-        });
         this.addEventListener('scroll', () => this.markScrolled());
         this.addEventListener('scroll', () => this.markScrolled());
-        this.initIntersectionObserver();
     }
     }
 
 
     render () {
     render () {
+        // This element has "flex-direction: reverse", so elements here are
+        // shown in reverse order.
         return html`
         return html`
-            ${ this.model.ui?.get('chat-content-spinner-top') ? html`<span class="spinner fa fa-spinner centered"></span>` : '' }
+            <div class="chat-content__notifications">${this.model.getNotificationsText()}</div>
             <converse-message-history
             <converse-message-history
                 .model=${this.model}
                 .model=${this.model}
-                .observer=${this.observer}
                 .messages=${[...this.model.messages.models]}>
                 .messages=${[...this.model.messages.models]}>
             </converse-message-history>
             </converse-message-history>
-            <div class="chat-content__notifications">${this.model.getNotificationsText()}</div>
+            ${ this.model.ui?.get('chat-content-spinner-top') ? html`<span class="spinner fa fa-spinner centered"></span>` : '' }
         `;
         `;
     }
     }
 
 
-    updated () {
-        const scrolled = this.model.get('scrolled');
-        if (this.was_scrolled_up === scrolled) {
-            this.debouncedMaintainScroll();
-        } else {
-            this.was_scrolled_up = scrolled;
-            if (!this.scrolled) {
-                this.scrollDown();
-            }
-        }
-    }
-
-    initIntersectionObserver () {
-      if (this.observer) {
-          this.observer.disconnect();
-      } else {
-          const options = {
-              root: this,
-              threshold: [0.1]
-          }
-          const handler = ev => this.setAnchoredMessage(ev);
-          this.observer = new IntersectionObserver(handler, options);
-      }
-    }
-
     /**
     /**
      * Called when the chat content is scrolled up or down.
      * Called when the chat content is scrolled up or down.
      * We want to record when the user has scrolled away from
      * We want to record when the user has scrolled away from
@@ -95,11 +63,14 @@ export default class ChatContent extends CustomElement {
      */
      */
     _markScrolled () {
     _markScrolled () {
         let scrolled = true;
         let scrolled = true;
-        const is_at_bottom = this.scrollTop + this.clientHeight >= this.scrollHeight;
+        const is_at_bottom = this.scrollTop === 0;
+        const is_at_top =
+            Math.ceil(this.clientHeight-this.scrollTop) >= (this.scrollHeight-Math.ceil(this.scrollHeight/20));
+
         if (is_at_bottom) {
         if (is_at_bottom) {
             scrolled = false;
             scrolled = false;
             onScrolledDown(this.model);
             onScrolledDown(this.model);
-        } else if (this.scrollTop === 0) {
+        } else if (is_at_top) {
             /**
             /**
              * Triggered once the chat's message area has been scrolled to the top
              * Triggered once the chat's message area has been scrolled to the top
              * @event _converse#chatBoxScrolledUp
              * @event _converse#chatBoxScrolledUp
@@ -113,31 +84,15 @@ export default class ChatContent extends CustomElement {
         }
         }
     }
     }
 
 
-    setAnchoredMessage (entries) {
-        if (!this.model?.ui || this.model.ui.get('chat-content-spinner-top')) {
+    scrollDown () {
+        if (this.model.get('scrolled')) {
             return;
             return;
         }
         }
-        entries = entries.filter(e => e.isIntersecting);
-        const current = entries.reduce((p, c) => c.boundingClientRect.y >= (p?.boundingClientRect.y || 0) ? c : p, null);
-        if (current) {
-            this.anchored_message = current.target;
-        }
-    }
-
-    maintainScrollPosition () {
-        if (this.was_scrolled_up) {
-            this.anchored_message?.scrollIntoView(true);
-        } else {
-            this.scrollDown();
-        }
-    }
-
-    scrollDown () {
         if (this.scrollTo) {
         if (this.scrollTo) {
             const behavior = this.scrollTop ? 'smooth' : 'auto';
             const behavior = this.scrollTop ? 'smooth' : 'auto';
-            this.scrollTo({ 'top': this.scrollHeight, behavior });
+            this.scrollTo({ 'top': 0, behavior });
         } else {
         } else {
-            this.scrollTop = this.scrollHeight;
+            this.scrollTop = 0;
         }
         }
         /**
         /**
          * Triggered once the converse-chat-content element has been scrolled down to the bottom.
          * Triggered once the converse-chat-content element has been scrolled down to the bottom.

+ 0 - 2
src/shared/chat/message-history.js

@@ -51,7 +51,6 @@ export default class MessageHistory extends CustomElement {
     static get properties () {
     static get properties () {
         return {
         return {
             model: { type: Object },
             model: { type: Object },
-            observer: { type: Object },
             messages: { type: Array }
             messages: { type: Array }
         }
         }
     }
     }
@@ -68,7 +67,6 @@ export default class MessageHistory extends CustomElement {
         const day = getDayIndicator(model);
         const day = getDayIndicator(model);
         const templates = day ? [day] : [];
         const templates = day ? [day] : [];
         const message = html`<converse-chat-message
         const message = html`<converse-chat-message
-            .observer=${this.observer}
             jid="${this.model.get('jid')}"
             jid="${this.model.get('jid')}"
             mid="${model.get('id')}"></converse-chat-message>`
             mid="${model.get('id')}"></converse-chat-message>`
 
 

+ 1 - 6
src/shared/chat/message.js

@@ -24,8 +24,7 @@ export default class Message extends CustomElement {
     static get properties () {
     static get properties () {
         return {
         return {
             jid: { type: String },
             jid: { type: String },
-            mid: { type: String },
-            observer: { type: Object }
+            mid: { type: String }
         }
         }
     }
     }
 
 
@@ -60,10 +59,6 @@ export default class Message extends CustomElement {
         }
         }
     }
     }
 
 
-    firstUpdated () {
-        this.observer.observe(this);
-    }
-
     getProps () {
     getProps () {
         return Object.assign(
         return Object.assign(
             this.model.toJSON(),
             this.model.toJSON(),

+ 8 - 0
src/shared/chat/styles/chat-content.scss

@@ -0,0 +1,8 @@
+
+converse-chat-content {
+    display: flex;
+    flex-direction: column-reverse;
+    height: 100%;
+    justify-content: space-between;
+    overflow: auto;
+}