debian-mirror-gitlab/app/assets/javascripts/notes/mixins/discussion_navigation.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

113 lines
3.2 KiB
JavaScript
Raw Normal View History

2020-03-13 15:44:24 +05:30
import { mapGetters, mapActions, mapState } from 'vuex';
2022-11-25 23:54:43 +05:30
import { scrollToElement, contentTop } from '~/lib/utils/common_utils';
2020-04-08 14:13:33 +05:30
2022-10-11 01:57:18 +05:30
function getAllDiscussionElements() {
2022-11-25 23:54:43 +05:30
const containerEl = window.mrTabs?.currentAction === 'diffs' ? '.diffs' : '.notes';
2022-10-11 01:57:18 +05:30
return Array.from(
2022-11-25 23:54:43 +05:30
document.querySelectorAll(
`${containerEl} div[data-discussion-id]:not([data-discussion-resolved])`,
),
2022-10-11 01:57:18 +05:30
);
}
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) {
2022-11-25 23:54:43 +05:30
const discussion = getDiscussion();
const id = discussion.dataset.discussionId;
ctx.expandDiscussion({ discussionId: id });
scrollToElement(discussion, scrollOptions);
2022-10-11 01:57:18 +05:30
}
2018-11-18 11:00:15 +05:30
export default {
2020-03-13 15:44:24 +05:30
computed: {
...mapGetters([
'nextUnresolvedDiscussionId',
'previousUnresolvedDiscussionId',
'getDiscussion',
]),
...mapState({
2021-03-08 18:12:59 +05:30
currentDiscussionId: (state) => state.notes.currentDiscussionId,
2020-03-13 15:44:24 +05:30
}),
},
2018-11-18 11:00:15 +05:30
methods: {
2020-03-13 15:44:24 +05:30
...mapActions(['expandDiscussion', 'setCurrentDiscussionId']),
2022-11-25 23:54:43 +05:30
...mapActions('diffs', ['scrollToFile', 'disableVirtualScroller']),
async jumpToNextDiscussion(scrollOptions) {
await this.disableVirtualScroller();
2020-03-13 15:44:24 +05:30
2022-10-11 01:57:18 +05:30
handleJumpForBothPages(
getNextDiscussion,
this,
this.nextUnresolvedDiscussionId,
scrollOptions,
);
2020-03-13 15:44:24 +05:30
},
2022-11-25 23:54:43 +05:30
async jumpToPreviousDiscussion(scrollOptions) {
await this.disableVirtualScroller();
2022-10-11 01:57:18 +05:30
handleJumpForBothPages(
getPreviousDiscussion,
this,
this.previousUnresolvedDiscussionId,
scrollOptions,
);
2020-03-13 15:44:24 +05:30
},
2020-10-24 23:57:45 +05:30
jumpToFirstUnresolvedDiscussion() {
this.setCurrentDiscussionId(null)
.then(() => {
this.jumpToNextDiscussion();
})
.catch(() => {});
},
2018-11-18 11:00:15 +05:30
},
};