diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-23 15:09:40 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-23 15:09:40 +0000 |
commit | e01e71a98f4c2d3492d99993d67e7277a2ead698 (patch) | |
tree | d43754b3eebf6b32feb442ad29c967f088e51536 /app/assets/javascripts/notes/mixins | |
parent | db90a0f7e36108df2c57f28bf84b733faceb6ee2 (diff) | |
download | gitlab-ce-e01e71a98f4c2d3492d99993d67e7277a2ead698.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/notes/mixins')
-rw-r--r-- | app/assets/javascripts/notes/mixins/discussion_navigation.js | 99 |
1 files changed, 81 insertions, 18 deletions
diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js index 45df91796fc..10c897d2d2a 100644 --- a/app/assets/javascripts/notes/mixins/discussion_navigation.js +++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js @@ -1,5 +1,5 @@ import { mapGetters, mapActions, mapState } from 'vuex'; -import { scrollToElementWithContext, scrollToElement } from '~/lib/utils/common_utils'; +import { scrollToElementWithContext, scrollToElement, contentTop } from '~/lib/utils/common_utils'; import { updateHistory } from '~/lib/utils/url_utility'; import eventHub from '../event_hub'; @@ -94,8 +94,6 @@ function jumpToDiscussion(self, discussion) { if (activeTab === 'diffs' && isDiffDiscussion) { diffsJump(self, id, firstNoteId); - } else if (activeTab === 'show') { - discussionJump(self, id); } else { switchToDiscussionsTabAndJumpTo(self, id); } @@ -105,11 +103,10 @@ function jumpToDiscussion(self, discussion) { /** * @param {object} self Component instance with mixin applied * @param {function} fn Which function used to get the target discussion's id - * @param {string} [discussionId=this.currentDiscussionId] Current discussion id, will be null if discussions have not been traversed yet */ -function handleDiscussionJump(self, fn, discussionId = self.currentDiscussionId) { +function handleDiscussionJump(self, fn) { const isDiffView = window.mrTabs.currentAction === 'diffs'; - const targetId = fn(discussionId, isDiffView); + const targetId = fn(self.currentDiscussionId, isDiffView); const discussion = self.getDiscussion(targetId); const discussionFilePath = discussion?.diff_file?.file_path; @@ -127,6 +124,70 @@ function handleDiscussionJump(self, fn, discussionId = self.currentDiscussionId) }); } +function getAllDiscussionElements() { + return Array.from( + document.querySelectorAll('[data-discussion-id]:not([data-discussion-resolved])'), + ); +} + +function hasReachedPageEnd() { + return document.body.scrollHeight <= Math.ceil(window.scrollY + window.innerHeight); +} + +function findNextClosestVisibleDiscussion(discussionElements) { + const offsetHeight = contentTop(); + let isActive; + const index = discussionElements.findIndex((element) => { + const { y } = element.getBoundingClientRect(); + const visibleHorizontalOffset = Math.ceil(y) - offsetHeight; + // handle rect rounding errors + isActive = visibleHorizontalOffset < 2; + return visibleHorizontalOffset >= 0; + }); + return [discussionElements[index], index, isActive]; +} + +function getNextDiscussion() { + const discussionElements = getAllDiscussionElements(); + const firstDiscussion = discussionElements[0]; + if (hasReachedPageEnd()) { + return firstDiscussion; + } + const [nextClosestDiscussion, index, isActive] = findNextClosestVisibleDiscussion( + discussionElements, + ); + if (nextClosestDiscussion && !isActive) { + return nextClosestDiscussion; + } + const nextDiscussion = discussionElements[index + 1]; + if (!nextClosestDiscussion || !nextDiscussion) { + return firstDiscussion; + } + return nextDiscussion; +} + +function getPreviousDiscussion() { + const discussionElements = getAllDiscussionElements(); + const lastDiscussion = discussionElements[discussionElements.length - 1]; + const [, index] = findNextClosestVisibleDiscussion(discussionElements); + const previousDiscussion = discussionElements[index - 1]; + if (previousDiscussion) { + return previousDiscussion; + } + return lastDiscussion; +} + +function handleJumpForBothPages(getDiscussion, ctx, fn, scrollOptions) { + if (window.mrTabs.currentAction !== 'show') { + handleDiscussionJump(ctx, fn); + } else { + const discussion = getDiscussion(); + const id = discussion.dataset.discussionId; + ctx.expandDiscussion({ discussionId: id }); + scrollToElement(discussion, scrollOptions); + } +} + export default { computed: { ...mapGetters([ @@ -142,12 +203,22 @@ export default { ...mapActions(['expandDiscussion', 'setCurrentDiscussionId']), ...mapActions('diffs', ['scrollToFile']), - jumpToNextDiscussion() { - handleDiscussionJump(this, this.nextUnresolvedDiscussionId); + jumpToNextDiscussion(scrollOptions) { + handleJumpForBothPages( + getNextDiscussion, + this, + this.nextUnresolvedDiscussionId, + scrollOptions, + ); }, - jumpToPreviousDiscussion() { - handleDiscussionJump(this, this.previousUnresolvedDiscussionId); + jumpToPreviousDiscussion(scrollOptions) { + handleJumpForBothPages( + getPreviousDiscussion, + this, + this.previousUnresolvedDiscussionId, + scrollOptions, + ); }, jumpToFirstUnresolvedDiscussion() { @@ -157,13 +228,5 @@ export default { }) .catch(() => {}); }, - - /** - * Go to the next discussion from the given discussionId - * @param {String} discussionId The id we are jumping from - */ - jumpToNextRelativeDiscussion(discussionId) { - handleDiscussionJump(this, this.nextUnresolvedDiscussionId, discussionId); - }, }, }; |