Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
50bf708
Open new tab when clicking file tree with mouse wheel
bytedream May 28, 2025
83e925a
Use own function instead
bytedream May 29, 2025
0941d5f
Merge branch 'main' into mouse-wheel-click-file-tree
bytedream Jun 15, 2025
91069cf
use click.middle instead of auxclick
bytedream Jun 15, 2025
2b5e119
also check if ctrl key was pressed
bytedream Jun 16, 2025
7fef0bb
Merge branch 'main' into mouse-wheel-click-file-tree
bytedream Jun 16, 2025
06ac1c9
update comment
bytedream Jun 16, 2025
10d9471
check meta key in addition to ctrl
bytedream Jun 16, 2025
9c4a8e2
add aux click check to doLoadDirContent
bytedream Jun 16, 2025
9915581
add sub module aux click support
bytedream Jun 16, 2025
3c6e803
Merge branch 'main' into mouse-wheel-click-file-tree
bytedream Jun 18, 2025
ee2f52a
use `a` for file tree files
bytedream Jun 18, 2025
2bf13d0
Merge branch 'main' into mouse-wheel-click-file-tree
bytedream Jun 18, 2025
0c8c45f
use class to disable default link styling
bytedream Jun 18, 2025
e2655f3
move plain click check to utils
bytedream Jun 18, 2025
35ab11f
mark mouse event explicitly null
bytedream Jun 18, 2025
ed23d70
update docs
bytedream Jun 18, 2025
7914f27
Merge branch 'main' into mouse-wheel-click-file-tree
wxiaoguang Jun 19, 2025
156de30
refactor
wxiaoguang Jun 19, 2025
5519577
refactor
wxiaoguang Jun 19, 2025
ef3873c
refactor
wxiaoguang Jun 19, 2025
f01e51f
prevent page reload on subtree load
bytedream Jun 19, 2025
390b63e
Merge branch 'main' into mouse-wheel-click-file-tree
GiteaBot Jun 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions web_src/js/components/ViewFileTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ async function loadViewContent(url: string) {
}

async function navigateTreeView(treePath: string) {
const url = `${props.repoLink}/src/${props.currentRefNameSubURL}/${pathEscapeSegments(treePath)}`;
const url = getWebUrl(treePath);
window.history.pushState({treePath, url}, null, url);
selectedItem.value = treePath;
await loadViewContent(url);
}

function getWebUrl(treePath: string) {
return `${props.repoLink}/src/${props.currentRefNameSubURL}/${pathEscapeSegments(treePath)}`;
}

onMounted(async () => {
selectedItem.value = props.treePath;
files.value = await loadChildren('', props.treePath);
Expand All @@ -58,7 +62,7 @@ onMounted(async () => {
<template>
<div class="view-file-tree-items" ref="elRoot">
<!-- only render the tree if we're visible. in many cases this is something that doesn't change very often -->
<ViewFileTreeItem v-for="item in files" :key="item.name" :item="item" :selected-item="selectedItem" :navigate-view-content="navigateTreeView" :load-children="loadChildren"/>
<ViewFileTreeItem v-for="item in files" :key="item.name" :item="item" :selected-item="selectedItem" :get-web-url="getWebUrl" :navigate-view-content="navigateTreeView" :load-children="loadChildren"/>
</div>
</template>

Expand Down
47 changes: 30 additions & 17 deletions web_src/js/components/ViewFileTreeItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ const props = defineProps<{
item: Item,
navigateViewContent:(treePath: string) => void,
loadChildren:(treePath: string, subPath?: string) => Promise<Item[]>,
getWebUrl:(treePath: string) => string,
selectedItem?: string,
}>();

const isLoading = ref(false);
const children = ref(props.item.children);
const collapsed = ref(!props.item.children);

const doLoadChildren = async () => {
const doLoadChildren = async (e?: MouseEvent) => {
// the event is only not undefined if the user explicitly clicked on the directory item toggle. the preventDefault
// stops the event from bubbling up and causing a directory content load
e?.preventDefault();

collapsed.value = !collapsed.value;
if (!collapsed.value && props.loadChildren) {
isLoading.value = true;
Expand All @@ -35,38 +40,42 @@ const doLoadChildren = async () => {
}
};

const doLoadDirContent = () => {
const doLoadDirContent = (e: MouseEvent) => {
// only load the directory content without a window refresh if the user didn't press any special key
if (e.button !== 0 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return;
e.preventDefault();

doLoadChildren();
props.navigateViewContent(props.item.fullPath);
};

const doLoadFileContent = () => {
props.navigateViewContent(props.item.fullPath);
};
const doLoadFileContent = (e: MouseEvent) => {
if (e.button !== 0 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return;
e.preventDefault();

const doGotoSubModule = () => {
location.href = props.item.submoduleUrl;
props.navigateViewContent(props.item.fullPath);
};
</script>

<!--title instead of tooltip above as the tooltip needs too much work with the current methods, i.e. not being loaded or staying open for "too long"-->
<template>
<div
<a
v-if="item.entryMode === 'commit'" class="tree-item type-submodule"
:title="item.entryName"
@click.stop="doGotoSubModule"
:href="getWebUrl(item.fullPath)"
>
<!-- submodule -->
<div class="item-content">
<!-- eslint-disable-next-line vue/no-v-html -->
<span class="tw-contents" v-html="item.entryIcon"/>
<span class="gt-ellipsis tw-flex-1">{{ item.entryName }}</span>
</div>
</div>
<div
</a>
<a
v-else-if="item.entryMode === 'symlink'" class="tree-item type-symlink"
:class="{'selected': selectedItem === item.fullPath}"
:title="item.entryName"
:href="getWebUrl(item.fullPath)"
@click.stop="doLoadFileContent"
>
<!-- symlink -->
Expand All @@ -75,11 +84,12 @@ const doGotoSubModule = () => {
<span class="tw-contents" v-html="item.entryIcon"/>
<span class="gt-ellipsis tw-flex-1">{{ item.entryName }}</span>
</div>
</div>
<div
</a>
<a
v-else-if="item.entryMode !== 'tree'" class="tree-item type-file"
:class="{'selected': selectedItem === item.fullPath}"
:title="item.entryName"
:href="getWebUrl(item.fullPath)"
@click.stop="doLoadFileContent"
>
<!-- file -->
Expand All @@ -88,11 +98,12 @@ const doGotoSubModule = () => {
<span class="tw-contents" v-html="item.entryIcon"/>
<span class="gt-ellipsis tw-flex-1">{{ item.entryName }}</span>
</div>
</div>
<div
</a>
<a
v-else class="tree-item type-directory"
:class="{'selected': selectedItem === item.fullPath}"
:title="item.entryName"
:href="getWebUrl(item.fullPath)"
@click.stop="doLoadDirContent"
>
<!-- directory -->
Expand All @@ -105,10 +116,10 @@ const doGotoSubModule = () => {
<span class="tw-contents" v-html="(!collapsed && item.entryIconOpen) ? item.entryIconOpen : item.entryIcon"/>
<span class="gt-ellipsis">{{ item.entryName }}</span>
</div>
</div>
</a>

<div v-if="children?.length" v-show="!collapsed" class="sub-items">
<ViewFileTreeItem v-for="childItem in children" :key="childItem.entryName" :item="childItem" :selected-item="selectedItem" :navigate-view-content="navigateViewContent" :load-children="loadChildren"/>
<ViewFileTreeItem v-for="childItem in children" :key="childItem.entryName" :item="childItem" :selected-item="selectedItem" :get-web-url="getWebUrl" :navigate-view-content="navigateViewContent" :load-children="loadChildren"/>
</div>
</template>
<style scoped>
Expand All @@ -131,6 +142,8 @@ const doGotoSubModule = () => {
}

.tree-item {
color: inherit;
text-decoration: inherit;
display: grid;
grid-template-columns: 16px 1fr;
grid-template-areas: "toggle content";
Expand Down
Loading