8000 Fix tree pruning and allow user to set cutoff by tjomson · Pull Request #698 · git-truck/git-truck · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix tree pruning and allow user to set cutoff #698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion src/analyzer/analyze.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ export type AnalyzationStatus = "Starting" | "Hydrating" | "GeneratingChart"

export let analyzationStatus: AnalyzationStatus = "Starting"

export function setAnalyzationStatus(newStatus: AnalyzationStatus) {
analyzationStatus = newStatus
}

export async function analyze(args: TruckConfig): Promise<AnalyzerData> {
analyzationStatus = "Starting"
GitCaller.initInstance(args.path)
Expand Down Expand Up @@ -267,7 +271,6 @@ export async function analyze(args: TruckConfig): Promise<AnalyzerData> {
})

if (repoTreeError) throw repoTreeError
analyzationStatus = "Hydrating"

const [hydrateResult, hydratedRepoTreeError] = await describeAsyncJob({
job: () => hydrateData(repoTree),
Expand Down
3 changes: 2 additions & 1 deletion src/analyzer/hydrate.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getCoAuthors } from "./coauthors.server"
import { log } from "./log.server"
import { gitLogRegex, contribRegex } from "./constants"
import { cpus } from "os"
import { setAnalyzationStatus } from "./analyze.server"

let renamedFiles: Map<string, { path: string; timestamp: number }[]>
let authors: Set<string>
Expand Down Expand Up @@ -114,7 +115,7 @@ export async function hydrateData(commit: GitCommitObject): Promise<[HydratedGit
log.warn(
"This repo has a lot of commits, so nodejs might run out of memory. Consider setting the environment variable NODE_OPTIONS to --max-old-space-size=4096 and rerun Git Truck"
)

setAnalyzationStatus("Hydrating")
// Sync threads every commitBundleSize commits to reset commits map, to reduce peak memory usage
for (let index = 0; index < commitCount; index += commitBundleSize) {
progress = index
Expand Down
18 changes: 8 additions & 10 deletions src/components/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const Chart = memo(function Chart({
const { searchResults } = useSearch()
const size = useDeferredValue(rawSize)
const { analyzerData } = useData()
const { chartType, sizeMetric, depthType, hierarchyType, labelsVisible } = useOptions()
const { chartType, sizeMetric, depthType, hierarchyType, labelsVisible, renderCutoff } = useOptions()
const { path } = usePath()
const { clickedObject, setClickedObject } = useClickedObject()
const { setPath } = usePath()
Expand Down Expand Up @@ -86,8 +86,8 @@ export const Chart = memo(function Chart({

const nodes = useMemo(() => {
if (size.width === 0 || size.height === 0) return []
return createPartitionedHiearchy(commit, size, chartType, sizeMetric, path).descendants()
}, [size, commit, chartType, sizeMetric, path])
return createPartitionedHiearchy(commit, size, chartType, sizeMetric, path, renderCutoff).descendants()
}, [size, commit, chartType, sizeMetric, path, renderCutoff])

useEffect(() => {
setHoveredObject(null)
Expand Down Expand Up @@ -354,7 +354,8 @@ function createPartitionedHiearchy(
size: { height: number; width: number },
chartType: ChartType,
sizeMetricType: SizeMetricType,
path: string
path: string,
renderCutoff: number
) {
const root = data.tree as HydratedGitTreeObject

Expand Down Expand Up @@ -391,7 +392,7 @@ function createPartitionedHiearchy(
return Object.keys(hydratedBlob.authors ?? {}).length
}
})

const cutOff = Number.isNaN(renderCutoff) ? 2 : renderCutoff
switch (chartType) {
case "TREE_MAP":
const treeMapPartition = treemap<HydratedGitObject>()
Expand All @@ -405,7 +406,7 @@ function createPartitionedHiearchy(

filterTree(tmPartition, (child) => {
const cast = child as HierarchyRectangularNode<HydratedGitObject>
return (isBlob(child.data) && cast.x0 >= 1 && cast.y0 >= 1) || isTree(child.data)
return (cast.x1 - cast.x0) >= cutOff && (cast.y1 - cast.y0) >= cutOff
})

return tmPartition
Expand All @@ -414,14 +415,11 @@ function createPartitionedHiearchy(
const bubbleChartPartition = pack<HydratedGitObject>()
.size([size.width, size.height - estimatedLetterHeightForDirText])
.padding(bubblePadding)

const bPartition = bubbleChartPartition(hiearchy)

filterTree(bPartition, (child) => {
const cast = child as HierarchyCircularNode<HydratedGitObject>
return (isBlob(child.data) && cast.r >= 1) || isTree(child.data)
return cast.r >= cutOff
})

return bPartition
default:
throw Error("Invalid chart type")
Expand Down
29 changes: 26 additions & 3 deletions src/components/Options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import type { ChartType, HierarchyType } from "../contexts/OptionsContext"
import { Chart, Hierarchy, useOptions } from "../contexts/OptionsContext"
import { CheckboxWithLabel } from "./util"
import { Icon } from "@mdi/react"
import { memo } from "react"
import { memo, useTransition } from "react"
import anitruck from "~/assets/truck.gif"

import {
mdiChartBubble,
mdiChartTree,
Expand All @@ -26,7 +28,8 @@ import {
mdiViewModule,
mdiCog,
mdiFileTree,
mdiFamilyTree
mdiFamilyTree,
mdiContentCut
} from "@mdi/js"
import type { SizeMetricType } from "~/metrics/sizeMetric"
import { SizeMetric } from "~/metrics/sizeMetric"
Expand All @@ -50,14 +53,16 @@ export const Options = memo(function Options() {
sizeMetric,
hierarchyType,
transitionsEnabled,
renderCutoff,
setTransitionsEnabled,
labelsVisible,
setLabelsVisible,
setMetricType,
setChartType,
setDepthType,
setHierarchyType,
setSizeMetricType
setSizeMetricType,
setRenderCutoff
} = useOptions()

const [linkMetricAndSizeMetric, setLinkMetricAndSizeMetric] = useLocalStorage<boolean>(
Expand Down Expand Up @@ -101,6 +106,8 @@ export const Options = memo(function Options() {
LAST_CHANGED: "LAST_CHANGED"
}

const [isTransitioning, startTransition] = useTransition()

return (
<>
{/* <h2 className="card__title">
Expand Down Expand Up @@ -237,6 +244,22 @@ export const Options = memo(function Options() {
<Icon className="ml-1.5" path={mdiLabel} size="1.25em" />
Labels
</CheckboxWithLabel>
<label
className="label flex w-full items-center justify-start gap-2 text-sm"
title="Adjust the item rendering size threshold"
>
<span className="flex grow items-center gap-2">
<Icon className="ml-1.5" path={mdiContentCut} size="1.25em" />
Pixel render cut-off {isTransitioning ? <img src={anitruck} alt="..." className="h-5" /> : ""}
</span>
<input
type="number"
min={0}
defaultValue={renderCutoff}
className="mr-1 w-12 place-self-end border-b-2"
=> startTransition(() => setRenderCutoff(x.target.valueAsNumber))}
/>
</label>
</fieldset>
</div>
</>
Expand Down
7 changes: 6 additions & 1 deletion src/components/Providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,12 @@ export function Providers({ children, data }: ProvidersProps) {
setOptions((prevOptions) => ({
...(prevOptions ?? getDefaultOptionsContextValue()),
labelsVisible: visible
}))
})),
setRenderCutoff: (renderCutoff: number) =>
setOptions((prevOptions) => ({
...(prevOptions ?? getDefaultOptionsContextValue()),
renderCutoff: renderCutoff
})),
}),
[options]
)
Expand Down
17 changes: 14 additions & 3 deletions src/components/util.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { HTMLAttributes } from "react"
import { useTransition, type HTMLAttributes } from "react"
import { Icon } from "@mdi/react"
import { mdiCheckboxOutline, mdiCheckboxBlankOutline, mdiMenuUp, mdiClose } from "@mdi/js"
import clsx from "clsx"
import anitruck from "~/assets/truck.gif"

export const CloseButton = ({
className = "",
Expand Down Expand Up @@ -54,11 +55,21 @@ export function CheckboxWithLabel({
checkedIcon?: string
uncheckedIcon?: string
} & Omit<React.HTMLAttributes<HTMLLabelElement>, "onChange" | "checked">) {
const [isTransitioning, startTransition] = useTransition()

return (
<label className={`label flex w-full items-center justify-start gap-2 ${className}`} {...props}>
<span className="flex grow items-center gap-2">{children}</span>
<span className="flex grow items-center gap-2">
{children}
{isTransitioning ? <img src={anitruck} alt="..." className="h-5" /> : ""}
</span>
<Icon className="place-self-end" path={checked ? checkedIcon : uncheckedIcon} size={1} />
<input type="checkbox" checked={checked} className="hidden" />
<input
type="checkbox"
defaultChecked={checked}
=> startTransition(() => onChange(e))}
className="hidden"
/>
</label>
)
}
Expand Down
8 changes: 7 additions & 1 deletion src/contexts/OptionsContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type Options = {
authorshipType: AuthorshipType
transitionsEnabled: boolean
labelsVisible: boolean
renderCutoff: number
}

export type OptionsContextType = Options & {
Expand All @@ -40,6 +41,7 @@ export type OptionsContextType = Options & {
setLabelsVisible: (labelsVisible: boolean) => void
setDepthType: (depthType: DepthType) => void
setHierarchyType: (hierarchyType: HierarchyType) => void
setRenderCutoff: (renderCutoff: number) => void
}

export const OptionsContext = createContext<OptionsContextType | undefined>(undefined)
Expand All @@ -61,7 +63,8 @@ const defaultOptions: Options = {
sizeMetric: Object.keys(SizeMetric)[0] as SizeMetricType,
authorshipType: Object.keys(Authorship)[0] as AuthorshipType,
transitionsEnabled: true,
labelsVisible: true
labelsVisible: true,
renderCutoff: 2
}

export function getDefaultOptionsContextValue(savedOptions: Partial<Options> = {}): OptionsContextType {
Expand Down Expand Up @@ -91,6 +94,9 @@ export function getDefaultOptionsContextValue(savedOptions: Partial<Options> = {
},
setLabelsVisible: () => {
throw new Error("No labelsVisibleSetter provided")
},
setRenderCutoff: () => {
throw new Error("No renderCutoffSetter provided")
}
}
}
0