flow experiment

This commit is contained in:
Christian Benincasa
2025-10-16 15:25:04 -04:00
parent cd7c4f331d
commit 7d80d4d22a
6 changed files with 239 additions and 1 deletions

153
pnpm-lock.yaml generated
View File

@@ -549,6 +549,9 @@ importers:
'@uidotdev/usehooks':
specifier: ^2.4.1
version: 2.4.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@xyflow/react':
specifier: ^12.8.6
version: 12.8.6(@types/react@18.2.15)(immer@10.0.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
axios:
specifier: ^1.11.0
version: 1.11.0
@@ -3130,6 +3133,24 @@ packages:
'@types/conventional-commits-parser@5.0.0':
resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==}
'@types/d3-color@3.1.3':
resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
'@types/d3-drag@3.0.7':
resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
'@types/d3-interpolate@3.0.4':
resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
'@types/d3-selection@3.0.11':
resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==}
'@types/d3-transition@3.0.9':
resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==}
'@types/d3-zoom@3.0.8':
resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==}
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
@@ -3564,6 +3585,15 @@ packages:
'@vue/shared@3.5.20':
resolution: {integrity: sha512-SoRGP596KU/ig6TfgkCMbXkr4YJ91n/QSdMuqeP5r3hVIYA3CPHUBCc7Skak0EAKV+5lL4KyIh61VA/pK1CIAA==}
'@xyflow/react@12.8.6':
resolution: {integrity: sha512-SksAm2m4ySupjChphMmzvm55djtgMDPr+eovPDdTnyGvShf73cvydfoBfWDFllooIQ4IaiUL5yfxHRwU0c37EA==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
'@xyflow/system@0.0.70':
resolution: {integrity: sha512-PpC//u9zxdjj0tfTSmZrg3+sRbTz6kop/Amky44U2Dl51sxzDTIUfXMwETOYpmr2dqICWXBIJwXL2a9QWtX2XA==}
'@yao-pkg/pkg-fetch@3.5.24':
resolution: {integrity: sha512-FPESCH1uXCYui6jeDp2aayWuFHR39w+uU1r88nI6JWRvPYOU64cHPUV/p6GSFoQdpna7ip92HnrZKbBC60l0gA==}
hasBin: true
@@ -4061,6 +4091,9 @@ packages:
citty@0.1.6:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
classcat@5.0.5:
resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==}
clean-stack@2.2.0:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
@@ -4315,6 +4348,44 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
d3-color@3.1.0:
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
engines: {node: '>=12'}
d3-dispatch@3.0.1:
resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
engines: {node: '>=12'}
d3-drag@3.0.0:
resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
engines: {node: '>=12'}
d3-ease@3.0.1:
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
engines: {node: '>=12'}
d3-interpolate@3.0.1:
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
engines: {node: '>=12'}
d3-selection@3.0.0:
resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
engines: {node: '>=12'}
d3-timer@3.0.1:
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
engines: {node: '>=12'}
d3-transition@3.0.1:
resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
engines: {node: '>=12'}
peerDependencies:
d3-selection: 2 - 3
d3-zoom@3.0.0:
resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
engines: {node: '>=12'}
dargs@8.1.0:
resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==}
engines: {node: '>=12'}
@@ -11122,6 +11193,27 @@ snapshots:
dependencies:
'@types/node': 22.10.7
'@types/d3-color@3.1.3': {}
'@types/d3-drag@3.0.7':
dependencies:
'@types/d3-selection': 3.0.11
'@types/d3-interpolate@3.0.4':
dependencies:
'@types/d3-color': 3.1.3
'@types/d3-selection@3.0.11': {}
'@types/d3-transition@3.0.9':
dependencies:
'@types/d3-selection': 3.0.11
'@types/d3-zoom@3.0.8':
dependencies:
'@types/d3-interpolate': 3.0.4
'@types/d3-selection': 3.0.11
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
@@ -11727,6 +11819,29 @@ snapshots:
'@vue/shared@3.5.20': {}
'@xyflow/react@12.8.6(@types/react@18.2.15)(immer@10.0.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@xyflow/system': 0.0.70
classcat: 5.0.5
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.4.6(@types/react@18.2.15)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
'@xyflow/system@0.0.70':
dependencies:
'@types/d3-drag': 3.0.7
'@types/d3-interpolate': 3.0.4
'@types/d3-selection': 3.0.11
'@types/d3-transition': 3.0.9
'@types/d3-zoom': 3.0.8
d3-drag: 3.0.0
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-zoom: 3.0.0
'@yao-pkg/pkg-fetch@3.5.24':
dependencies:
https-proxy-agent: 5.0.1
@@ -12321,6 +12436,8 @@ snapshots:
dependencies:
consola: 3.4.2
classcat@5.0.5: {}
clean-stack@2.2.0: {}
clean-stack@5.2.0:
@@ -12562,6 +12679,42 @@ snapshots:
csstype@3.1.3: {}
d3-color@3.1.0: {}
d3-dispatch@3.0.1: {}
d3-drag@3.0.0:
dependencies:
d3-dispatch: 3.0.1
d3-selection: 3.0.0
d3-ease@3.0.1: {}
d3-interpolate@3.0.1:
dependencies:
d3-color: 3.1.0
d3-selection@3.0.0: {}
d3-timer@3.0.1: {}
d3-transition@3.0.1(d3-selection@3.0.0):
dependencies:
d3-color: 3.1.0
d3-dispatch: 3.0.1
d3-ease: 3.0.1
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-timer: 3.0.1
d3-zoom@3.0.0:
dependencies:
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
dargs@8.1.0: {}
data-view-buffer@1.0.1:

File diff suppressed because one or more lines are too long

View File

@@ -31,6 +31,7 @@
"@tunarr/shared": "workspace:*",
"@tunarr/types": "workspace:*",
"@uidotdev/usehooks": "^2.4.1",
"@xyflow/react": "^12.8.6",
"axios": "^1.11.0",
"bowser": "^2.11.0",
"color": "^5.0.0",

View File

@@ -0,0 +1,60 @@
import type { EdgeChange, NodeChange } from '@xyflow/react';
import {
Background,
Controls,
ReactFlow,
addEdge,
applyEdgeChanges,
applyNodeChanges,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useCallback, useState } from 'react';
type Node = {
id: string;
position: { x: number; y: number };
data: { label: string };
};
const initialNodes = [
{ id: 'n1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
{ id: 'n2', position: { x: 0, y: 100 }, data: { label: 'Node 2' } },
];
type Edge = { id: string; source: string; target: string };
const initialEdges = [{ id: 'n1-n2', source: 'n1', target: 'n2' }];
export const FlowPage = () => {
const [nodes, setNodes] = useState(initialNodes);
const [edges, setEdges] = useState(initialEdges);
const onNodesChange = useCallback(
(changes: NodeChange<Node>[]) =>
setNodes((nodesSnapshot) => applyNodeChanges(changes, nodesSnapshot)),
[],
);
const onEdgesChange = useCallback(
(changes: EdgeChange<Edge>[]) =>
setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)),
[],
);
const onConnect = useCallback(
(params) => setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)),
[],
);
return (
<div style={{ width: '50%', height: 'calc(85vh)' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
>
<Background />
<Controls />
</ReactFlow>
</div>
);
};

View File

@@ -30,6 +30,7 @@ import { Route as SettingsFfmpegImport } from './routes/settings/ffmpeg';
import { Route as MediasourcesMediaSourceIdImport } from './routes/media_sources/$mediaSourceId';
import { Route as LibraryFillersImport } from './routes/library/fillers';
import { Route as LibraryCustomShowsImport } from './routes/library/custom-shows';
import { Route as DebugFlowImport } from './routes/debug/flow';
import { Route as ChannelsTestImport } from './routes/channels/test';
import { Route as ChannelsNewImport } from './routes/channels/new';
import { Route as ChannelsChannelIdImport } from './routes/channels/$channelId';
@@ -148,6 +149,11 @@ const LibraryCustomShowsRoute = LibraryCustomShowsImport.update({
getParentRoute: () => rootRoute,
} as any);
const DebugFlowRoute = DebugFlowImport.update({
path: '/debug/flow',
getParentRoute: () => rootRoute,
} as any);
const ChannelsTestRoute = ChannelsTestImport.update({
path: '/channels/test',
getParentRoute: () => rootRoute,
@@ -322,6 +328,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ChannelsTestImport;
parentRoute: typeof rootRoute;
};
'/debug/flow': {
id: '/debug/flow';
path: '/debug/flow';
fullPath: '/debug/flow';
preLoaderRoute: typeof DebugFlowImport;
parentRoute: typeof rootRoute;
};
'/library/custom-shows': {
id: '/library/custom-shows';
path: '/library/custom-shows';
@@ -566,6 +579,7 @@ export const routeTree = rootRoute.addChildren({
ChannelsChannelIdRoute,
ChannelsNewRoute,
ChannelsTestRoute,
DebugFlowRoute,
LibraryCustomShowsRoute,
LibraryFillersRoute,
MediasourcesMediaSourceIdRoute,
@@ -604,6 +618,7 @@ export const routeTree = rootRoute.addChildren({
"/channels/$channelId",
"/channels/new",
"/channels/test",
"/debug/flow",
"/library/custom-shows",
"/library/fillers",
"/media_sources/$mediaSourceId",
@@ -665,6 +680,9 @@ export const routeTree = rootRoute.addChildren({
"/channels/test": {
"filePath": "channels/test.tsx"
},
"/debug/flow": {
"filePath": "debug/flow.tsx"
},
"/library/custom-shows": {
"filePath": "library/custom-shows.tsx"
},

View File

@@ -0,0 +1,6 @@
import { createFileRoute } from '@tanstack/react-router';
import { FlowPage } from '../../pages/debug/FlowPage.tsx';
export const Route = createFileRoute('/debug/flow')({
component: FlowPage,
});