Skip to content

Commit

Permalink
Merge pull request #2458 from posit-dev/dotnomad/virtual-files
Browse files Browse the repository at this point in the history
Virtualize the Project Files tree list
  • Loading branch information
dotNomad authored Dec 6, 2024
2 parents 3f22dbb + b8d9eee commit a13b259
Show file tree
Hide file tree
Showing 15 changed files with 458 additions and 226 deletions.
37 changes: 36 additions & 1 deletion extensions/vscode/webviews/homeView/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion extensions/vscode/webviews/homeView/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"axios": "1.7.4",
"eventsource": "^2.0.2",
"pinia": "^2.1.7",
"vue": "^3.4.21"
"vue": "^3.4.21",
"vue-virtual-scroller": "^2.0.0-beta.8"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.4",
Expand Down
13 changes: 10 additions & 3 deletions extensions/vscode/webviews/homeView/src/HostConduitService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
WebviewToHostMessage,
WebviewToHostMessageType,
} from "../../../src/types/messages/webviewToHostMessages";
import { useHomeStore } from "./stores/home";
import { useFileStore } from "src/stores/file";
import { useHomeStore } from "src/stores/home";
import { vscodeAPI } from "src/vscode";

let hostConduit: HostConduit | undefined = undefined;
Expand Down Expand Up @@ -196,8 +197,14 @@ const onSaveSelectionMsg = () => {
};

const onRefreshFilesMsg = (msg: RefreshFilesMsg) => {
const home = useHomeStore();
home.files = msg.content.files;
const fileStore = useFileStore();

// If the root file has changed, reset the expanded directories
if (msg.content.files.abs !== fileStore.files?.abs) {
fileStore.expandedDirs = new Set();
}

fileStore.files = msg.content.files;
};

const onUpdatePythonPackages = (msg: UpdatePythonPackages) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
class="tree-item"
:class="{
'align-icon-with-twisty': alignIconWithTwisty,
collapsible: $slots.default,
collapsible: isExpandable,
'text-list-emphasized': listStyle === 'emphasized',
'text-foreground': listStyle === 'default',
'text-list-deemphasized': listStyle === 'deemphasized',
}"
>
<div
class="tree-item-container"
:class="virtualized ? 'class-hover' : undefined"
:title="tooltip"
v-on="{
click: $slots.default ? toggleExpanded : undefined,
click: isExpandable ? toggleExpanded : undefined,
}"
>
<div class="indent">
Expand All @@ -22,8 +23,8 @@
<div
class="twisty-container text-icon"
:class="[
{ codicon: $slots.default },
$slots.default
{ codicon: isExpandable },
expandable || $slots.default
? expanded
? 'codicon-chevron-down'
: 'codicon-chevron-right'
Expand Down Expand Up @@ -52,13 +53,15 @@
</div>
</div>

<div v-show="$slots.default && expanded" class="tree-item-children">
<div v-show="isExpandable && expanded" class="tree-item-children">
<slot :indent-level="indentLevel + 1" />
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from "vue";
import ActionToolbar, { ActionButton } from "src/components/ActionToolbar.vue";
export type TreeItemStyle = "emphasized" | "default" | "deemphasized";
Expand All @@ -74,22 +77,33 @@ interface Props {
codicon?: string;
actions?: ActionButton[];
indentLevel?: number;
expandable?: boolean;
virtualized?: boolean;
}
withDefaults(defineProps<Props>(), {
const props = withDefaults(defineProps<Props>(), {
listStyle: "default",
indentLevel: 1,
expandable: false,
virtualized: false,
});
defineSlots<{
const slots = defineSlots<{
default(props: { indentLevel: number }): any;
description(): any;
postDecor(): any;
}>();
const emits = defineEmits(["expand", "collapse"]);
const toggleExpanded = () => {
expanded.value = !expanded.value;
emits(expanded.value ? "expand" : "collapse");
};
const isExpandable = computed((): Boolean => {
return Boolean(slots.default || props.expandable);
});
</script>

<style lang="scss" scoped>
Expand Down Expand Up @@ -192,7 +206,8 @@ const toggleExpanded = () => {
flex-grow: 100;
}
&:hover {
.hover &.class-hover,
&:not(.class-hover):hover {
color: var(--vscode-list-hoverForeground, var(--vscode-foreground));
background-color: var(--vscode-list-hoverBackground);
Expand All @@ -209,7 +224,8 @@ const toggleExpanded = () => {
}
}
&:hover .actions,
.hover &.class-hover .actions,
&:not(.class-hover):hover .actions,
&:focus-within .actions {
display: initial;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,32 @@
class="tree-item"
:class="{
'align-icon-with-twisty': alignIconWithTwisty,
collapsible: $slots.default,
collapsible: isExpandable,
'text-list-emphasized': listStyle === 'emphasized',
'text-foreground': listStyle === 'default',
'text-list-deemphasized': listStyle === 'deemphasized',
}"
>
<div class="tree-item-container" :title="tooltip">
<div
class="tree-item-container"
:class="virtualized ? 'class-hover' : undefined"
:title="tooltip"
>
<div class="indent">
<div v-for="_ in indentLevel - 1" class="indent-guide"></div>
</div>
<div
class="twisty-container text-icon"
:class="[
{ codicon: $slots.default },
$slots.default
{ codicon: isExpandable },
expandable || $slots.default
? expanded
? 'codicon-chevron-down'
: 'codicon-chevron-right'
: undefined,
]"
v-on="{
click: $slots.default ? toggleExpanded : undefined,
click: isExpandable ? toggleExpanded : undefined,
}"
/>
<vscode-checkbox
Expand All @@ -46,13 +50,15 @@
</div>
</div>

<div v-show="$slots.default && expanded" class="tree-item-children">
<div v-show="isExpandable && expanded" class="tree-item-children">
<slot :indent-level="indentLevel + 1" />
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from "vue";
import ActionToolbar, { ActionButton } from "src/components/ActionToolbar.vue";
export type TreeItemStyle = "emphasized" | "default" | "deemphasized";
Expand All @@ -69,23 +75,32 @@ interface Props {
alignIconWithTwisty?: boolean;
actions?: ActionButton[];
indentLevel?: number;
expandable?: boolean;
virtualized?: boolean;
}
withDefaults(defineProps<Props>(), {
const props = withDefaults(defineProps<Props>(), {
listStyle: "default",
indentLevel: 1,
expandable: false,
virtualized: false,
});
defineSlots<{
const slots = defineSlots<{
default(props: { indentLevel: number }): any;
postDecor(): any;
}>();
defineEmits(["check", "uncheck"]);
const emits = defineEmits(["check", "uncheck", "expand", "collapse"]);
const toggleExpanded = () => {
expanded.value = !expanded.value;
emits(expanded.value ? "expand" : "collapse");
};
const isExpandable = computed((): Boolean => {
return Boolean(slots.default || props.expandable);
});
</script>

<style lang="scss" scoped>
Expand Down Expand Up @@ -174,7 +189,8 @@ const toggleExpanded = () => {
flex-grow: 100;
}
&:hover {
.hover &.class-hover,
&:not(.class-hover):hover {
color: var(--vscode-list-hoverForeground, var(--vscode-foreground));
background-color: var(--vscode-list-hoverBackground);
Expand All @@ -191,7 +207,8 @@ const toggleExpanded = () => {
}
}
&:hover .actions,
.hover &.class-hover .actions,
&:not(.class-hover):hover .actions,
&:focus-within .actions {
display: initial;
}
Expand Down
Loading

0 comments on commit a13b259

Please sign in to comment.