gitlab-ce/app/assets/javascripts/diffs/components/diffs_file_tree.vue

164 lines
4.3 KiB
Vue

<script>
import { debounce } from 'lodash';
import { mapActions } from 'pinia';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import { getCookie, setCookie } from '~/lib/utils/common_utils';
import * as types from '~/diffs/store/mutation_types';
import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
import FileBrowserHeight from '~/diffs/components/file_browser_height.vue';
import {
INITIAL_TREE_WIDTH,
MIN_TREE_WIDTH,
TREE_HIDE_STATS_WIDTH,
TREE_LIST_WIDTH_STORAGE_KEY,
} from '../constants';
import TreeList from './tree_list.vue';
export default {
name: 'DiffsFileTree',
components: { FileBrowserHeight, TreeList, PanelResizer },
minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: window.innerWidth / 2,
props: {
loadedFiles: {
type: Object,
required: false,
default: null,
},
floatingResize: {
type: Boolean,
required: false,
default: false,
},
totalFilesCount: {
type: [Number, String],
default: undefined,
required: false,
},
groupBlobsListItems: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
treeWidth: INITIAL_TREE_WIDTH,
rowHeight: 0,
floating: false,
newWidth: 0,
cachedHeight: 0,
cachedTop: 0,
};
},
computed: {
hideFileStats() {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
applyNewWidthDebounced() {
return debounce(this.applyNewWidth, 250);
},
floatingWrapperStyles() {
if (!this.floating) return undefined;
return {
height: `${this.cachedHeight}px`,
width: `${this.newWidth}px`,
top: `${this.cachedTop}px`,
};
},
},
watch: {
newWidth() {
this.applyNewWidthDebounced();
},
},
created() {
this.restoreTreeWidthUserPreference();
},
mounted() {
const computedStyles = getComputedStyle(this.$refs.root.$el);
this.rowHeight = parseInt(computedStyles.getPropertyValue('--file-row-height'), 10);
},
methods: {
...mapActions(useLegacyDiffs, {
setCurrentDiffFile: types.SET_CURRENT_DIFF_FILE,
}),
restoreTreeWidthUserPreference() {
const userPreference =
getCookie(TREE_LIST_WIDTH_STORAGE_KEY) || localStorage.getItem(TREE_LIST_WIDTH_STORAGE_KEY);
if (!userPreference) return;
this.treeWidth = parseInt(userPreference, 10);
},
onFileClick(file) {
this.setCurrentDiffFile(file.fileHash);
this.$emit('clickFile', file);
},
onResizeStart() {
if (!this.floatingResize) return;
this.floating = true;
this.newWidth = this.treeWidth;
const { height, top } = this.$el.getBoundingClientRect();
this.cachedHeight = height;
this.cachedTop = top;
},
onResizeEnd(size) {
setCookie(TREE_LIST_WIDTH_STORAGE_KEY, size);
if (!this.floatingResize) return;
this.floating = false;
this.cachedHeight = null;
this.newWidth = null;
this.cachedTop = null;
this.treeWidth = size;
},
onSizeUpdate(value) {
if (this.floating) {
this.newWidth = value;
} else {
this.treeWidth = value;
}
},
applyNewWidth() {
if (this.newWidth) {
this.treeWidth = this.newWidth;
}
},
},
};
</script>
<template>
<file-browser-height
ref="root"
data-testid="file-browser-tree"
:style="{ width: `${treeWidth}px` }"
class="rd-app-sidebar diff-tree-list"
:class="{ 'diff-tree-list-floating': floating }"
>
<div
data-testid="file-browser-floating-wrapper"
class="diff-tree-list-floating-wrapper"
:style="floatingWrapperStyles"
>
<panel-resizer
class="diff-tree-list-resizer gl-hidden lg:gl-block"
:start-size="treeWidth"
:min-size="$options.minTreeWidth"
:max-size="$options.maxTreeWidth"
side="right"
@update:size="onSizeUpdate"
@resize-start="onResizeStart"
@resize-end="onResizeEnd"
/>
<tree-list
:hide-file-stats="hideFileStats"
:loaded-files="loadedFiles"
:total-files-count="totalFilesCount"
:row-height="rowHeight"
:group-blobs-list-items="groupBlobsListItems"
@clickFile="onFileClick"
@toggleFolder="$emit('toggleFolder', $event)"
/>
</div>
</file-browser-height>
</template>