Skip to content

Commit

Permalink
feat(Grid View): ✨ Add dots visualisation to grid view
Browse files Browse the repository at this point in the history
It shows one dot for each 1000 bytes of the file size of that cell
  • Loading branch information
SkepticMystic committed Jul 31, 2021
1 parent bc41548 commit 146e126
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 101 deletions.
43 changes: 35 additions & 8 deletions src/BreadcrumbsSettingTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,33 @@ export class BreadcrumbsSettingTab extends PluginSettingTab {
});
});

new Setting(trailDetails)
.setName("Grid view dots")
.setDesc(
"If the grid view is visible, shows dots based on the file size of each cell."
)
.addToggle((toggle) =>
toggle.setValue(plugin.settings.gridDots).onChange(async (value) => {
plugin.settings.gridDots = value;
await plugin.saveSettings();
await plugin.drawTrail();
})
);

const dotsColour = trailDetails.createDiv();
dotsColour.createEl("h4", {
text: "Dots colour",
});
const dotsColourPicker = dotsColour.createEl("input", {
type: "color",
});

dotsColourPicker.value = plugin.settings.heatmapColour;
dotsColourPicker.addEventListener("change", async () => {
plugin.settings.dotsColour = dotsColourPicker.value;
await plugin.saveSettings();
});

new Setting(trailDetails)
.setName("Grid view heatmap")
.setDesc(
Expand All @@ -200,17 +227,17 @@ export class BreadcrumbsSettingTab extends PluginSettingTab {
})
);

const mainColourDiv = trailDetails.createDiv();
mainColourDiv.createEl("h4", {
const heatmapColour = trailDetails.createDiv();
heatmapColour.createEl("h4", {
text: "Heat map colour",
});
const mainColourPicker = mainColourDiv.createEl("input", { type: "color" });

mainColourPicker.value = plugin.settings.heatmapColour;
const heatmapColourPicker = heatmapColour.createEl("input", {
type: "color",
});

mainColourPicker.addEventListener("change", async () => {
plugin.settings.heatmapColour = mainColourPicker.value;
console.log(mainColourPicker.value);
heatmapColourPicker.value = plugin.settings.heatmapColour;
heatmapColourPicker.addEventListener("change", async () => {
plugin.settings.heatmapColour = heatmapColourPicker.value;
await plugin.saveSettings();
});

Expand Down
226 changes: 134 additions & 92 deletions src/TrailGrid.svelte
Original file line number Diff line number Diff line change
@@ -1,132 +1,174 @@
<script lang="ts">
import type { App,TFile,View } from "obsidian";
import type BreadcrumbsPlugin from "src/main";
import { closeImpliedLinks, normalise, openOrSwitch,padArray,runs,transpose } from "src/sharedFunctions";
export let sortedTrails: string[][]
export let app: App;
export let plugin: BreadcrumbsPlugin;
const settings = plugin.settings;
const currFile = app.workspace.getActiveFile();
const activeLeafView = app.workspace.activeLeaf.view;
function resolvedClass(toFile: string, currFile: TFile): string {
import { range } from "lodash";
import type { App, TFile, View } from "obsidian";
import type BreadcrumbsPlugin from "src/main";
import {
closeImpliedLinks,
normalise,
openOrSwitch,
padArray,
runs,
transpose,
} from "src/sharedFunctions";
export let sortedTrails: string[][];
export let app: App;
export let plugin: BreadcrumbsPlugin;
const settings = plugin.settings;
const currFile = app.workspace.getActiveFile();
const activeLeafView = app.workspace.activeLeaf.view;
function resolvedClass(toFile: string, currFile: TFile): string {
return app.metadataCache.unresolvedLinks[currFile.path][toFile] > 0
? "internal-link is-unresolved breadcrumbs-link"
: "internal-link breadcrumbs-link";
}
function hoverPreview(event: MouseEvent, view: View): void {
const targetEl = event.target as HTMLElement;
view.app.workspace.trigger("hover-link", {
event,
source: view.getViewType(),
hoverParent: view,
targetEl,
linktext: targetEl.innerText,
? "internal-link is-unresolved breadcrumbs-link"
: "internal-link breadcrumbs-link";
}
function hoverPreview(event: MouseEvent, view: View): void {
const targetEl = event.target as HTMLElement;
view.app.workspace.trigger("hover-link", {
event,
source: view.getViewType(),
hoverParent: view,
targetEl,
linktext: targetEl.innerText,
});
}
const allCells = [...new Set(sortedTrails.reduce((a, b) => [...a, ...b]))];
const wordCounts: { [cell: string]: number } = {};
allCells.forEach(
(cell) =>
(wordCounts[cell] = app.metadataCache.getFirstLinkpathDest(
cell,
currFile.path
).stat.size)
);
// const data: {[cell: string]: number} = {}
// allCells.forEach(cell => data[cell] = app.metadataCache.getFileCache(app.metadataCache.getFirstLinkpathDest(cell, currFile.path))?.links.length ?? 0);
const children: { [cell: string]: number } = {};
allCells.forEach(
(cell) =>
(children[cell] = (
closeImpliedLinks(
plugin.currGraphs.gChildren,
plugin.currGraphs.gParents
).successors(cell) ?? []
).length)
);
const normalisedData = normalise(Object.values(children));
allCells.forEach((cell, i) => {
children[cell] = normalisedData[i];
});
}
const allCells = [... new Set(sortedTrails.reduce((a, b) => [...a, ...b]))]
// const data: {[cell: string]: number} = {}
// allCells.forEach(cell => data[cell] = app.metadataCache.getFileCache(app.metadataCache.getFirstLinkpathDest(cell, currFile.path))?.links.length ?? 0);
const children: {[cell: string]: number} = {};
allCells.forEach(cell => children[cell] = (closeImpliedLinks(plugin.currGraphs.gChildren, plugin.currGraphs.gParents).successors(cell) ?? []).length)
const normalisedData = normalise(Object.values(children));
allCells.forEach((cell, i) => {
children[cell] = normalisedData[i]
})
// const normalisedData = allCells.forEach(cell => {
// })
// const normalisedData = allCells.forEach(cell => {
// })
// const links: {[cell: string]: number}[] = []
// data.forEach(cell => links[Object.keys(cell)[0]] = (Object.values(cell)[0]?.links.length ?? 0))
// const links: {[cell: string]: number}[] = []
// data.forEach(cell => links[Object.keys(cell)[0]] = (Object.values(cell)[0]?.links.length ?? 0))
// console.log(data)
// console.log(data)
const maxLength = Math.max(...sortedTrails.map(trail => trail.length))
const paddedTrails: string[][] = sortedTrails.map(trail => padArray(trail, maxLength))
const maxLength = Math.max(...sortedTrails.map((trail) => trail.length));
const paddedTrails: string[][] = sortedTrails.map((trail) =>
padArray(trail, maxLength)
);
// const permutations: string[][][] = permute(paddedTrails.map(trail => [trail[0]]))
// const permutations: string[][][] = permute(paddedTrails.map(trail => [trail[0]]))
// // permutations.map(trails => sum(transpose(trails).map(runs).map(runs => runs.length)))
// // permutations.map(trails => sum(transpose(trails).map(runs).map(runs => runs.length)))
// const ALLRuns = permutations.map(permutation => transpose(permutation).map(runs))
// const runsPerRun = ALLRuns.map(runs => runs[0].length)
// const minRunLength = Math.min(...runsPerRun);
// const indexOfMinRun = runsPerRun.indexOf(minRunLength);
// const minRun = ALLRuns[indexOfMinRun]
// const ALLRuns = permutations.map(permutation => transpose(permutation).map(runs))
// const runsPerRun = ALLRuns.map(runs => runs[0].length)
// const minRunLength = Math.min(...runsPerRun);
// const indexOfMinRun = runsPerRun.indexOf(minRunLength);
// const minRun = ALLRuns[indexOfMinRun]
const transposedTrails: string[][] = transpose(paddedTrails);
const allRuns = transposedTrails.map(runs);
const transposedTrails: string[][] = transpose(paddedTrails);
const allRuns = transposedTrails.map(runs);
const intToCol = (int:number) => ('#' + int.toString(16).padStart(6, '0'));
// allRuns.forEach(run => console.log(intToCol(data[run[0].value])))
// debug(settings, {maxLength, paddedTrails, transposedTrails, permutations, ALLRuns, runsPerRun, minRunLength: Math.min(...runsPerRun), minRun})
const intToCol = (int: number) => "#" + int.toString(16).padStart(6, "0");
// allRuns.forEach(run => console.log(intToCol(data[run[0].value])))
// debug(settings, {maxLength, paddedTrails, transposedTrails, permutations, ALLRuns, runsPerRun, minRunLength: Math.min(...runsPerRun), minRun})
</script>

<div class="breadcrumbs-trail-grid" style="
<div
class="breadcrumbs-trail-grid"
style="
grid-template-columns: {'1fr '.repeat(transposedTrails.length)};
grid-template-rows: {'1fr '.repeat(sortedTrails.length)}">

{#each transposedTrails as col, i}

grid-template-rows: {'1fr '.repeat(sortedTrails.length)}"
>
{#each transposedTrails as col, i}
{#each allRuns[i] as step}
<div
<div
class="breadcrumbs-trail-grid-item
{resolvedClass(step.value, currFile)}
{step.value === '' ? 'breadcrumbs-filler' : ''}"

{step.value === '' ? 'breadcrumbs-filler' : ''}"
style="
grid-area: {step.first + 1} / {i + 1} /
{step.last + 2} / {i + 2};
{settings.gridHeatmap
? `background-color: ${settings.heatmapColour}${Math.round((children[step.value] * 200) + 55).toString(16)}`
: ''}"

on:click={(e) =>
openOrSwitch(app, step.value, currFile, e)
}
on:mouseover={(e) => hoverPreview(e,activeLeafView)}>
{step.value}
</div>
{settings.gridHeatmap
? `background-color: ${settings.heatmapColour}${Math.round(
children[step.value] * 200 + 55
).toString(16)}`
: ''}"
on:click={(e) => openOrSwitch(app, step.value, currFile, e)}
on:mouseover={(e) => hoverPreview(e, activeLeafView)}
>
<div>{step.value}</div>
{#if step.value && settings.gridDots}
<div class="dots">
{#each range(Math.floor(wordCounts[step.value] / 1000)) as i}
<span
class="dot"
style="background-color: {settings.dotsColour}"
/>
{/each}
</div>
{/if}
</div>
{/each}

{/each}
{/each}
</div>


<style>
div.breadcrumbs-trail-grid {
div.breadcrumbs-trail-grid {
border: 2px solid var(--background-modifier-border);
display: grid;
align-items: stretch;
width: auto;
height: auto;
}
}
div.breadcrumbs-trail-grid-item {
div.breadcrumbs-trail-grid-item {
display: flex;
flex-direction: column;
border: 1px solid var(--background-modifier-border);
align-items: center;
justify-content: center;
padding: 2px;
font-size: smaller;
/* height: auto; */
}
}
div.breadcrumbs-trail-grid-item.breadcrumbs-filler {
div.breadcrumbs-trail-grid-item.breadcrumbs-filler {
opacity: 0.7;
}
</style>
}
/* .dots {
height: 10px;
} */
.dot {
height: 5px;
width: 5px;
border-radius: 50%;
display: inline-block;
}
</style>
2 changes: 2 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export interface BreadcrumbsSettings {
showRelationType: boolean;
showTrail: boolean;
trailOrTable: 1 | 2 | 3;
gridDots: boolean;
dotsColour: string;
gridHeatmap: boolean;
heatmapColour: string;
showAll: boolean;
Expand Down
3 changes: 2 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
closeImpliedLinks,
debug,
getDVMetadataCache,
getFileFrontmatterArr,
getNeighbourObjArr,
getObsMetadataCache,
} from "src/sharedFunctions";
Expand All @@ -36,6 +35,8 @@ const DEFAULT_SETTINGS: BreadcrumbsSettings = {
showRelationType: true,
showTrail: true,
trailOrTable: 3,
gridDots: false,
dotsColour: getComputedStyle(document.body).getPropertyValue("--text-accent"),
gridHeatmap: false,
heatmapColour: getComputedStyle(document.body).getPropertyValue(
"--text-accent"
Expand Down
2 changes: 2 additions & 0 deletions src/sharedFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,5 @@ export function permute(permutation: any[]): any[][] {
export function dropMD(path: string) {
return path.split(".md", 1)[0];
}

export const range = (n: number) => [...Array(5).keys()];

0 comments on commit 146e126

Please sign in to comment.