Skip to content

Commit

Permalink
Themes - dark mode included (#62)
Browse files Browse the repository at this point in the history
dark mode and themes support
---------

Co-authored-by: YU <111847207+YU000jp@users.noreply.github.com>
  • Loading branch information
mrparalon and YU000jp authored Nov 11, 2023
1 parent 464fb42 commit 72288d3
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 33 deletions.
22 changes: 17 additions & 5 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type Graph from "graphology";
import { afterUpdate, onMount } from "svelte";
import { onMount } from "svelte";
import { filter } from "./graph";
import Node from "./Node.svelte";
import Edge from "./Edge.svelte";
Expand All @@ -15,15 +15,30 @@
Mode,
NodeFilter,
} from "./stores";
import { setThemeColors } from "./settings/themes";
onMount(async () => {
logseq.App.onThemeModeChanged((event) => {
setThemeColors();
$settings.themeMode = event.mode;
});
logseq.App.onThemeChanged((event) => {
setThemeColors();
if (event.mode === "dark") {
$settings.themeMode = "dark";
} else {
$settings.themeMode = "light";
}
});
// @ts-ignore
logseq.on("ui:visible:changed", async ({ visible }) => {
store.visible(visible);
if (visible) {
store.reload();
}
});
$settings.themeMode = (await logseq.App.getUserConfigs()).preferredThemeMode;
if (logseq.settings) {
if (logseq.settings.filters) {
let filters: NodeFilter[] = logseq.settings.filters;
Expand Down Expand Up @@ -96,8 +111,7 @@
if (page) {
logseq.Editor.openInRightSidebar(page.uuid);
}
} else
if ($settings.mode === Mode.Navigate || metaDown) {
} else if ($settings.mode === Mode.Navigate || metaDown) {
const page = await logseq.Editor.getPage(+event.detail);
if (page) {
metaDown = false;
Expand Down Expand Up @@ -147,7 +161,6 @@
}
graphWas = graph;
return graph;
}
function filteredGraph(
Expand Down Expand Up @@ -216,7 +229,6 @@
bottom: 0;
left: 0;
font-family: Arial, Helvetica, sans-serif;
background: white;
width: 100%;
height: 100%;
}
Expand Down
56 changes: 37 additions & 19 deletions src/Sigma.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@
afterUpdate,
setContext,
} from "svelte";
import Sigma from "sigma";
import FA2Layout from "graphology-layout-forceatlas2/worker";
import forceAtlas2 from "graphology-layout-forceatlas2";
import forceLayout from "graphology-layout-force";
import ForceSupervisor from "graphology-layout-force/worker";
import Graph from "graphology";
import type { SigmaNodeEventPayload } from "sigma/sigma";
import type { Attributes } from "graphology-types";
Expand All @@ -27,33 +24,43 @@
import CircleNodeProgram from "sigma/rendering/webgl/programs/node.fast";
import getNodeProgramImage from "sigma/rendering/webgl/programs/node.image";
import { getTheme } from "./settings/themes";
import drawHover from "./sigma/drawHover";
import { ExtendedSigma } from "./sigma/sigma";
let sigmaRef: HTMLElement;
let sigma: Sigma | undefined;
let sigma: ExtendedSigma | undefined;
let fa2Layout: FA2Layout | undefined;
export let size: number;
const dispatch = createEventDispatcher();
const red = "#f87171";
const orange = "#fb923c";
const grey = "#a3a3a3";
setContext("sigma", {
getGraph: () => sigma?.getGraph(),
});
onMount(async () => {
const graph = new Graph();
sigma = new Sigma(graph, sigmaRef, {
const theme = getTheme($settings.themeMode);
sigma = new ExtendedSigma(graph, sigmaRef, {
allowInvalidContainer: true,
nodeReducer,
edgeReducer,
defaultNodeColor: grey,
defaultNodeColor: theme.nodeColor,
defaultEdgeColor: theme.edgeColor,
labelColor: {
color: theme.nodeLabelColor,
},
labelBackgroundColor: theme.nodeLabelBackground,
labelShadowColor: theme.nodeLabelShadowColor,
nodeProgramClasses: {
circle: CircleNodeProgram,
image: getNodeProgramImage(),
},
hoverRenderer: drawHover,
});
sigma.on("clickNode", handleNodeClick);
Expand Down Expand Up @@ -200,24 +207,22 @@
// update style on change settings
$: {
if (sigma) {
const theme = getTheme($settings.themeMode);
const graph = sigma.getGraph();
graph.forEachNode((node) => {
graph.updateEachNodeAttributes((node, data: Attributes) => {
data.color = grey;
return data;
});
sigma.setSetting("defaultEdgeColor", theme.edgeColor);
sigma.setSetting("defaultNodeColor", theme.nodeColor);
sigma.setSetting("labelColor", { color: theme.nodeLabelColor });
sigma.setSetting("labelBackgroundColor", theme.nodeLabelBackground);
sigma.setSetting("labelShadowColor", theme.nodeLabelShadowColor);
graph.updateEachNodeAttributes((_, attr) => {
attr.color = theme.nodeColor;
return attr;
});
$settings.filters.forEach((filter) => {
graph.updateEachNodeAttributes((node, attr: Attributes) => {
attr.highlighted = false;
attr.size = (attr.size ?? attr.size) + 2;
if (foundNodeIds?.includes(node)) {
attr.color = orange;
attr.highlighted = true;
attr.size = (attr.size ?? attr.size) + 2;
return attr;
} else if (
if (
filter.searchType === "color" &&
filter.foundNodeIds?.includes(node)
) {
Expand All @@ -227,8 +232,21 @@
return attr;
});
});
if (foundNodeIds) {
graph.updateEachNodeAttributes((node, attr: Attributes) => {
attr.highlighted = false;
attr.size = (attr.size ?? attr.size) + 2;
if (foundNodeIds?.includes(node)) {
attr.color = orange;
attr.highlighted = true;
attr.size = (attr.size ?? attr.size) + 2;
return attr;
}
return attr;
})
}
}
}
$: if (sigma && ($settings.pathA || $settings.pathB || $settings.search)) {
nodeIndex = nodeNameIndex($graph);
Expand Down
8 changes: 7 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "@unocss/reset/normalize.css";
import App from "./App.svelte";
import type * as CSS from "csstype";
import type { SettingSchemaDesc } from "@logseq/libs/dist/LSPlugin.user";
import {setThemeColors} from "./settings/themes";


const settingsSchema: SettingSchemaDesc[] = [
Expand Down Expand Up @@ -35,14 +36,19 @@ function createModel() {

async function main() {
const app = new App({
target: document.getElementById("app"),
target: document.getElementById("app") as Element,
});


setThemeColors();

const baseStyles: CSS.Properties = {
position: "fixed",
zIndex: 12,
height: "calc(100vh - 8px)",
top: "8px",
background: "var(--ls-primary-background-color)",
color: "var(--ls-primary-text-color)",
};

logseq.setMainUIInlineStyle(baseStyles);
Expand Down
15 changes: 9 additions & 6 deletions src/settings/Settings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@
section {
margin-bottom: 0.5rem;
}
.settings {
:global(.settings) {
position: fixed;
top: 40px;
right: 1vh;
Expand All @@ -208,18 +208,19 @@
border: 1px solid #a3a3a3;
padding: 0.5rem;
margin: 0;
background-color: rgba(255, 255, 255, 0.8);
background-color: var(--theme-secondary-background);
color: var(--theme-color);
}
input[type=search] {
:global(input[type=search]) {
tab-size: 4;
word-break: break-word;
border: 0 solid #e5e5e5;
border: 0 solid var(--theme-border-color);
box-sizing: border-box;
color: inherit;
margin: 0;
font: inherit;
appearance: none;
background-color: #fff;
background-color: var(--theme-background-color);
padding: .5rem .75rem;
border-radius: .25rem;
padding-left: .5rem;
Expand All @@ -246,7 +247,9 @@
height: 1.5rem;
font-size: 0.8rem;
border-radius: 0.25rem;
border: 1px solid #e5e5e5;
border: 1px solid var(--theme-border-color);
background-color: var(--theme-background-color);
color: var(--theme-color);
}
select:focus {
Expand Down
4 changes: 2 additions & 2 deletions src/settings/components/NodeFilter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@
input[type=search] {
tab-size: 4;
word-break: break-word;
border: 0 solid #e5e5e5;
border: 0 solid var(--theme-border-color);
box-sizing: border-box;
color: inherit;
margin: 0;
font: inherit;
appearance: none;
background-color: #fff;
background-color: var(--theme-background-color);
padding: .5rem .75rem;
border-radius: .25rem;
padding-left: .5rem;
Expand Down
46 changes: 46 additions & 0 deletions src/settings/themes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
interface Theme {
// Background color and text color inherited from Logseq
mode: "dark" | "light";
nodeColor: string;
edgeColor: string;
nodeLabelColor: string;
nodeLabelBackground: string;
nodeLabelShadowColor: string;
}

const lightTheme: Theme = {
mode: "light",
nodeColor: "#5c5c5c",
edgeColor: "#e5e5e5",
nodeLabelColor: "#000000",
nodeLabelBackground: "#ffffff",
nodeLabelShadowColor: "rgb(0, 0, 0)",
};

const darkTheme: Theme = {
mode: "dark",
nodeColor: "#aaaaaa",
edgeColor: "#444444",
nodeLabelColor: "#ffffff",
nodeLabelBackground: "rgb(0, 0, 0, 0.7)",
nodeLabelShadowColor: "#ffffff",
};

export const setThemeColors = () => {
const root = parent.document.querySelector(":root");
if (root) {
const rootStyles = getComputedStyle(root);
document.body.style.setProperty("--theme-background", rootStyles.getPropertyValue("--ls-primary-background-color") || "#ffffff");
document.body.style.setProperty("--theme-color", rootStyles.getPropertyValue("--ls-primary-text-color") || "#000000");
document.body.style.setProperty("--theme-accent-color", rootStyles.getPropertyValue("--ls-primary-accent-color") || "#000000");
document.body.style.setProperty("--theme-secondary-background", rootStyles.getPropertyValue("--ls-secondary-background-color") || "#000000");
document.body.style.setProperty("--theme-border-color", rootStyles.getPropertyValue("--ls-border-color") || "#000000");
}
};
export function getTheme(mode: "light" | "dark"): Theme {
if (mode === "light") {
return lightTheme;
} else {
return darkTheme;
}
}
62 changes: 62 additions & 0 deletions src/sigma/drawHover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { NodeDisplayData, PartialButFor } from "sigma/types";
import drawLabel from "sigma/rendering/canvas/label";
import type { ExtendedSettings } from "./sigma/sigma";

/**
* Draw an hovered node.
* - if there is no label => display a shadow on the node
* - if the label box is bigger than node size => display a label box that contains the node with a shadow
* - else node with shadow and the label box
*/
export default function drawHover(
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, "x" | "y" | "size" | "label" | "color">,
settings: ExtendedSettings,
): void {
const size = settings.labelSize,
font = settings.labelFont,
weight = settings.labelWeight;

context.font = `${weight} ${size}px ${font}`;

// Then we draw the label background
context.fillStyle = settings.labelBackgroundColor || "#FFF";
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 8;
context.shadowColor = settings.labelShadowColor || "#000";

const PADDING = 2;

if (typeof data.label === "string") {
const textWidth = context.measureText(data.label).width,
boxWidth = Math.round(textWidth + 5),
boxHeight = Math.round(size + 2 * PADDING),
radius = Math.max(data.size, size / 2) + PADDING;

const angleRadian = Math.asin(boxHeight / 2 / radius);
const xDeltaCoord = Math.sqrt(Math.abs(Math.pow(radius, 2) - Math.pow(boxHeight / 2, 2)));

context.beginPath();
context.moveTo(data.x + xDeltaCoord, data.y + boxHeight / 2);
context.lineTo(data.x + radius + boxWidth, data.y + boxHeight / 2);
context.lineTo(data.x + radius + boxWidth, data.y - boxHeight / 2);
context.lineTo(data.x + xDeltaCoord, data.y - boxHeight / 2);
context.arc(data.x, data.y, radius, angleRadian, -angleRadian);
context.closePath();
context.fill();
} else {
context.beginPath();
context.arc(data.x, data.y, data.size + PADDING, 0, Math.PI * 2);
context.closePath();
context.fill();
}

context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;

// And finally we draw the label
drawLabel(context, data, settings);
}

Loading

0 comments on commit 72288d3

Please sign in to comment.