From 83b6446d4344338cd7033a6f05e96032b72f78c5 Mon Sep 17 00:00:00 2001
From: Dennis Collaris <d.a.c.collaris@uu.nl>
Date: Mon, 5 Aug 2024 09:14:25 +0000
Subject: [PATCH] feat: support dark mode in matrix vis

---
 .../matrixvis/components/MatrixPixi.tsx       | 62 ++++++++++++-------
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx b/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx
index bcdb109fa..a6d98b55f 100644
--- a/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx
+++ b/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx
@@ -2,7 +2,7 @@ import { Edge, GraphQueryResult, Node, useML, useSearchResultData } from '@graph
 import { dataColors, visualizationColors } from 'config';
 import { Viewport } from 'pixi-viewport';
 import { Application, ColorSource, Container, FederatedPointerEvent, Graphics, IPointData, Point, Text } from 'pixi.js';
-import { useEffect, useRef, useState } from 'react';
+import { useEffect, useRef, useState, useImperativeHandle } from 'react';
 import { LinkType, NodeType } from '../types';
 import { NLPopup } from './MatrixPopup';
 
@@ -26,6 +26,8 @@ import {
   type Axis,
 } from 'd3';
 import { MatrixVisProps } from '../matrixvis';
+import { Theme } from '@graphpolaris/shared/lib/data-access/store/configSlice';
+import { useConfig } from '@graphpolaris/shared/lib/data-access/store';
 
 const styleMatrixSize = 50;
 
@@ -56,6 +58,14 @@ export const MatrixPixi = (props: Props) => {
     cellWidth: 100,
   };
 
+  const globalConfig = useConfig();
+
+  useEffect(() => {
+    if (props.graph) {
+      setup();
+    }
+  }, [globalConfig.theme]);
+
   let columnOrder: string[] = [];
   let rowOrder: string[] = [];
 
@@ -70,7 +80,13 @@ export const MatrixPixi = (props: Props) => {
   const isSetup = useRef(false);
   const ml = useML();
 
-  // const imperative = useRef<any>(null);
+  const imperative = useRef<any>(null);
+  useImperativeHandle(imperative, () => ({
+    getBackgroundColor() {
+      // Colors corresponding to .bg-light class
+      return globalConfig.theme === Theme.dark ? 0x121621 : 0xffffff;
+    },
+  }));
 
   let app: Application;
 
@@ -257,7 +273,7 @@ export const MatrixPixi = (props: Props) => {
 
     if (app == null) {
       app = new Application({
-        background: 0xffffff,
+        backgroundAlpha: 0,
         antialias: true,
         autoDensity: true,
         eventMode: 'auto',
@@ -267,21 +283,23 @@ export const MatrixPixi = (props: Props) => {
     }
 
     if (svg.current != null) {
-      select(svg.current).select('*').remove();
+      select(svg.current).selectAll('*').remove();
     }
+
     columnsContainer.removeChildren();
     app.stage.removeChildren();
 
     const size = ref.current?.getBoundingClientRect();
-    viewport.current = new Viewport({
-      screenWidth: size?.width || 1000,
-      screenHeight: size?.height || 1000,
-      worldWidth: size?.width || 1000,
-      worldHeight: size?.height || 1000,
-      stopPropagation: true,
-      events: app.renderer.events, // the interaction module is important for wheel to work properly when renderer.view is placed or scaled
-    });
-
+    if (viewport.current == null) {
+      viewport.current = new Viewport({
+        screenWidth: size?.width || 1000,
+        screenHeight: size?.height || 1000,
+        worldWidth: size?.width || 1000,
+        worldHeight: size?.height || 1000,
+        stopPropagation: true,
+        events: app.renderer.events, // the interaction module is important for wheel to work properly when renderer.view is placed or scaled
+      });
+    }
     app.stage.addChild(viewport.current);
 
     viewport.current.addChild(columnsContainer);
@@ -362,19 +380,19 @@ export const MatrixPixi = (props: Props) => {
     if (!props.graph) throw new Error('Graph is undefined; cannot setup matrix');
     const visMapping = []; // TODO type
 
-    let colorNeutralString = dataColors.neutral['5'];
+    let colorNeutralString = globalConfig.theme === Theme.dark ? dataColors.neutral['80'] : dataColors.neutral['15'];
     const colorNeutral = Color(colorNeutralString);
 
     // make adjacency
     // const adjacenyScale = scaleLinear([dataColors.neutral['5'], tailwindColors.entity.DEFAULT]);
-    const adjacenyScale = scaleLinear([colorNeutral, visualizationColors.GPSelected.colors[1][0]]);
+    const adjacenyScale = scaleLinear([colorNeutral, visualizationColors.GPPrimary.colors[1][0]]);
     visMapping.push({
       attribute: 'adjacency',
       encoding: settings.marks,
       colorScale: adjacenyScale,
       renderFunction: function (i: number, color: ColorSource, gfxContext: Graphics) {
         // Clear locally
-        gfxContext.beginFill(0xffffff, 1);
+        gfxContext.beginFill(imperative.current.getBackgroundColor(), 1);
         gfxContext.drawRect(0, i * config.cellHeight, config.cellWidth, config.cellHeight);
         gfxContext.endFill();
 
@@ -474,7 +492,7 @@ export const MatrixPixi = (props: Props) => {
       .attr('class', 'label')
       .style('text-anchor', 'middle')
       .style('alignment-baseline', 'hanging')
-      .style('fill', 'black')
+      .style('fill', globalConfig.theme === Theme.dark ? 'white' : 'black')
       .style('font-size', '14')
       .text(label);
 
@@ -572,7 +590,7 @@ export const MatrixPixi = (props: Props) => {
       .attr('class', 'label')
       .style('text-anchor', 'middle')
       .style('alignment-baseline', 'hanging')
-      .style('fill', 'black')
+      .style('fill', globalConfig.theme === Theme.dark ? 'white' : 'black')
       .style('font-size', '14')
       .text(label);
 
@@ -659,8 +677,8 @@ export const MatrixPixi = (props: Props) => {
             bottom: 0,
             width: styleMatrixSize,
             backdropFilter: 'blur(10px)',
-            background: 'rgba(255,255,255, 0.5)',
-            boxShadow: '1px 0px 0px 0px rgba(0,0,0,0.2)',
+            background: globalConfig.theme === Theme.dark ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255, 0.5)',
+            boxShadow: globalConfig.theme === Theme.dark ? '1px 0px 0px 0px rgba(255,255,255,0.2)' : '1px 0px 0px 0px rgba(0,0,0,0.2)',
           }}
         ></div>
         <div
@@ -672,8 +690,8 @@ export const MatrixPixi = (props: Props) => {
             right: 0,
             height: styleMatrixSize,
             backdropFilter: 'blur(10px)',
-            background: 'rgba(255,255,255, 0.5)',
-            boxShadow: `${styleMatrixSize}px 0px 0px 0px rgba(0,0,0,0.2)`,
+            background: globalConfig.theme === Theme.dark ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255, 0.5)',
+            boxShadow: globalConfig.theme === Theme.dark ? `${styleMatrixSize}px 1px 0px 0px rgba(255,255,255,0.2)` : `${styleMatrixSize}px 1px 0px 0px rgba(0,0,0,0.2)`,
           }}
         ></div>
         <svg
-- 
GitLab