Skip to content

Commit 333aa88

Browse files
shanimal08brianp
andauthored
feat: remove animation canvas entirely | move to animation package (#1457)
Description --- - most of the work was done in the new ~~[`tari-tower` repo](https://github.com/tari-labs/tari-tower)~~ [`@tari-project/tari-tower` repo](https://github.com/tari-project/tari-tower) - implemented typescript, and converted Classes to modules where i could - fixed type errors - added load/remove tower functions which are exported along with `setAnimationState` and `setAnimationProperties` - built and published as a lib - added [`@tari-project/tari-tower`](https://www.npmjs.com/package/@tari-project/tari-tower) package - removed old webgl build files - updated imports - added extra toggle loading state flag (to help in `useMiningUiStateMachine.ts`) - updated workflows so we can use the package Motivation and Context --- - toggling visual mode previously just hid the canvas, this removes the element entirely + frees up some gpu after removing the WEBGL renderer How Has This Been Tested? --- https://github.com/user-attachments/assets/c9b92155-1edb-4070-95c8-6834a863158a https://github.com/user-attachments/assets/9b9b5c95-73a8-437e-ac1e-052498341f1b https://github.com/user-attachments/assets/2fd12be6-ac7f-45bd-a48c-253a8036a750 What process can a PR reviewer use to test or verify this change? --- - run with visual mode on vs off and see GPU stats Breaking Changes --- - ~~yes, after this is merged you will need to install `@tari-labs/tari-tower` for local development~~ - nope, just `npm ci` after it's merged :3 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced an enhanced visual mode with improved loading indicators and smoother animation transitions powered by an external graphics module. - **Refactor** - Streamlined the page layout by removing embedded graphics initialization code and redundant elements, resulting in more efficient loading and clearer error feedback. - **Style** - Updated styling for key visual elements with revised identifiers to ensure a consistent and polished interface. - **Bug Fixes** - Improved error handling for WebGL support notifications and visual mode toggling. - **Chores** - Updated dependency versions for improved performance and stability. - Removed outdated licensing documentation for texture assets. - Removed unused TypeScript declarations and related files to clean up the codebase. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Brian Pearce <[email protected]>
1 parent 39ad3bd commit 333aa88

28 files changed

+265
-5057
lines changed

.license.ignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
./public/assets/glApp.js

index.html

Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
crossorigin
5858
/>
5959

60-
<script type="module" crossorigin src="/assets/glApp.js"></script>
6160
<title>Tari Universe | Testnet</title>
6261
<style>
6362
/* Poppins Font Faces */
@@ -190,78 +189,14 @@
190189
padding: 0;
191190
margin: 0;
192191
}
193-
194-
#canvas {
192+
#tower-canvas {
195193
position: absolute;
196194
pointer-events: auto;
197195
}
198196
</style>
199197
</head>
200198
<body>
201-
<main id="main">
202-
<div id="root"></div>
203-
<canvas id="canvas" style="opacity: 0"></canvas>
204-
<script type="module" src="src/main.tsx"></script>
205-
<script>
206-
let time;
207-
let lastRender;
208-
let targetFPS = 40;
209-
let frameInterval = 1 / targetFPS;
210-
211-
function preload() {
212-
glApp.preload(
213-
{
214-
canvas: document.getElementById('canvas'),
215-
orbitTarget: document.getElementById('canvas'),
216-
ASSETS_PATH: '/assets/',
217-
},
218-
() => {
219-
init();
220-
}
221-
);
222-
}
223-
224-
function init() {
225-
glApp.init();
226-
time = performance.now() / 1000;
227-
lastRender = time;
228-
window.addEventListener('resize', onResize);
229-
230-
onResize();
231-
animate();
232-
}
233-
234-
function animate() {
235-
let newTime = performance.now() / 1000;
236-
let dt = newTime - time;
237-
if (newTime - lastRender >= frameInterval) {
238-
lastRender = newTime;
239-
update(dt);
240-
time = newTime;
241-
}
242-
243-
requestAnimationFrame(animate);
244-
}
245-
246-
function update(dt) {
247-
glApp.render(dt);
248-
}
249-
250-
function onResize() {
251-
const sidebarOffset = 348 + 20; // sidebar + padding
252-
glApp.properties.cameraOffsetX = sidebarOffset / window.innerWidth;
253-
glApp.setSize(window.innerWidth, window.innerHeight);
254-
}
255-
256-
document.addEventListener('DOMContentLoaded', () => {
257-
if (!window.WebGL2RenderingContext && !window.WebGLRenderingContext) {
258-
console.error('WebGL not supported!');
259-
return;
260-
}
261-
262-
preload();
263-
});
264-
</script>
265-
</main>
199+
<div id="root"></div>
200+
<script type="module" src="src/main.tsx"></script>
266201
</body>
267202
</html>

package-lock.json

Lines changed: 116 additions & 91 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"dependencies": {
1818
"@floating-ui/react": "^0.27.4",
1919
"@lottiefiles/dotlottie-react": "^0.13.0",
20+
"@tari-project/tari-tower": "^0.0.16",
2021
"@tauri-apps/api": "^2.2.0",
2122
"@tauri-apps/plugin-clipboard-manager": "^2.2.0",
2223
"@tauri-apps/plugin-os": "^2.2.0",

public/assets/glApp.js

Lines changed: 0 additions & 4732 deletions
This file was deleted.

public/assets/models/BASE.buf

-175 KB
Binary file not shown.

public/assets/models/BOX.buf

-3.2 KB
Binary file not shown.

public/assets/models/COIN.buf

-15.1 KB
Binary file not shown.
-5.42 KB
Binary file not shown.
-49.3 KB
Binary file not shown.

public/assets/textures/LDR_RGB1_0.png

-47.6 KB
Binary file not shown.

public/assets/textures/LICENSES.txt

Lines changed: 0 additions & 8 deletions
This file was deleted.

public/assets/textures/gobo.jpg

-47.1 KB
Binary file not shown.
-88.4 KB
Binary file not shown.

src/App/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ const CurrentAppSection = memo(function CurrentAppSection() {
6262
});
6363

6464
export default function App() {
65+
const isAppReady = useIsAppReady();
66+
const isShuttingDown = useShuttingDown();
6567
const setError = useAppStateStore((s) => s.setError);
6668
const setIsWebglNotSupported = useUIStore((s) => s.setIsWebglNotSupported);
6769

@@ -75,7 +77,7 @@ export default function App() {
7577
return (
7678
<ThemeProvider>
7779
<GlobalReset />
78-
<GlobalStyle />
80+
<GlobalStyle $hideCanvas={!isAppReady || isShuttingDown} />
7981
<LazyMotion features={domAnimation} strict>
8082
<FloatingElements />
8183
<CurrentAppSection />

src/components/elements/ToggleSwitch.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const Wrapper = styled.label<{ $disabled?: boolean }>`
1010
${({ $disabled }) =>
1111
$disabled &&
1212
css`
13+
cursor: auto;
1314
pointer-events: none;
1415
opacity: 0.8;
1516
`}

src/containers/main/Dashboard/components/VisualMode.tsx

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { useCallback } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import styled from 'styled-components';
44
import { ToggleSwitch } from '@app/components/elements/ToggleSwitch.tsx';
5-
import { useAppConfigStore } from '@app/store/useAppConfigStore';
6-
import { useUIStore } from '@app/store/useUIStore';
5+
import { setVisualMode, useAppConfigStore } from '@app/store/useAppConfigStore';
6+
import { sidebarTowerOffset, TOWER_CANVAS_ID, useUIStore } from '@app/store/useUIStore';
77
import { Typography } from '@app/components/elements/Typography';
88
import {
99
SettingsGroup,
@@ -13,23 +13,51 @@ import {
1313
SettingsGroupWrapper,
1414
} from '@app/containers/floating/Settings/components/SettingsGroup.styles';
1515

16+
import { loadTowerAnimation, removeTowerAnimation, setAnimationState } from '@tari-project/tari-tower';
17+
1618
const ErrorTypography = styled(Typography)(({ theme }) => ({
1719
color: theme.palette.error.main,
1820
}));
1921

2022
function VisualMode() {
2123
const visualMode = useAppConfigStore((s) => s.visual_mode);
22-
const setVisualMode = useAppConfigStore((s) => s.setVisualMode);
24+
const visualModeToggleLoading = useAppConfigStore((s) => s.visualModeToggleLoading);
2325
const isWebglNotSupported = useUIStore((s) => s.isWebglNotSupported);
2426
const { t } = useTranslation('settings', { useSuspense: false });
2527

28+
const handleDisable = useCallback(() => {
29+
setVisualMode(false);
30+
removeTowerAnimation({ canvasId: TOWER_CANVAS_ID })
31+
.then(() => {
32+
// Force garbage collection to clean up WebGL context
33+
if (window.gc) {
34+
window.gc();
35+
}
36+
})
37+
.catch((e) => {
38+
console.error('Could not disable visual mode. Error at loadTowerAnimation:', e);
39+
setVisualMode(true);
40+
});
41+
}, []);
42+
const handleEnable = useCallback(() => {
43+
loadTowerAnimation({ canvasId: TOWER_CANVAS_ID, offset: sidebarTowerOffset })
44+
.then(() => {
45+
setVisualMode(true);
46+
setAnimationState('showVisual');
47+
})
48+
.catch((e) => {
49+
console.error('Could not enable visual mode. Error at loadTowerAnimation:', e);
50+
setVisualMode(false);
51+
});
52+
}, []);
53+
2654
const handleSwitch = useCallback(() => {
27-
const canvasElement = document.getElementById('canvas');
28-
if (canvasElement) {
29-
canvasElement.style.display = visualMode ? 'none' : 'block';
55+
if (visualMode) {
56+
handleDisable();
57+
} else {
58+
handleEnable();
3059
}
31-
setVisualMode(!visualMode);
32-
}, [setVisualMode, visualMode]);
60+
}, [handleDisable, handleEnable, visualMode]);
3361

3462
return (
3563
<SettingsGroupWrapper>
@@ -41,11 +69,14 @@ function VisualMode() {
4169
{isWebglNotSupported && <ErrorTypography color="error">{t('webgl-not-supported')}</ErrorTypography>}
4270
</SettingsGroupContent>
4371
<SettingsGroupAction style={{ alignItems: 'center' }}>
44-
<ToggleSwitch disabled={isWebglNotSupported} checked={visualMode} onChange={handleSwitch} />
72+
<ToggleSwitch
73+
disabled={visualModeToggleLoading || isWebglNotSupported}
74+
checked={visualMode}
75+
onChange={() => handleSwitch()}
76+
/>
4577
</SettingsGroupAction>
4678
</SettingsGroup>
4779
</SettingsGroupWrapper>
4880
);
4981
}
50-
5182
export default VisualMode;

src/glApp.d.ts

Lines changed: 0 additions & 72 deletions
This file was deleted.

src/global.d.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,57 @@
11
import { useAppStateStore } from '@app/store/appStateStore';
22
import { useMiningStore } from '@app/store/useMiningStore';
3-
import { setAnimationState } from '@app/visuals';
43
import { useEffect } from 'react';
4+
import { setAnimationState, animationStatus } from '@tari-project/tari-tower';
55
import { useMiningMetricsStore } from '@app/store/useMiningMetricsStore.ts';
6+
import { useAppConfigStore } from '@app/store/useAppConfigStore.ts';
67

78
export const useUiMiningStateMachine = () => {
89
const isMiningInitiated = useMiningStore((s) => s.miningInitiated);
910
const isChangingMode = useMiningStore((s) => s.isChangingMode);
1011
const cpuIsMining = useMiningMetricsStore((s) => s.cpu_mining_status.is_mining);
1112
const gpuIsMining = useMiningMetricsStore((s) => s.gpu_mining_status.is_mining);
1213
const setupComplete = useAppStateStore((s) => s.setupComplete);
14+
const visualMode = useAppConfigStore((s) => s.visual_mode);
15+
const visualModeToggleLoading = useAppConfigStore((s) => s.visualModeToggleLoading);
1316
const isMining = cpuIsMining || gpuIsMining;
1417

15-
const statusIndex = window?.glApp?.stateManager?.statusIndex;
18+
const indexTrigger = animationStatus;
1619

1720
useEffect(() => {
18-
const status = window?.glApp?.stateManager?.status;
19-
const notStarted = !status || status == 'not-started' || status == 'stop';
21+
let isLatestEffect = true;
22+
if (!visualMode || visualModeToggleLoading) return;
23+
const notStarted = !animationStatus || animationStatus == 'not-started';
2024
if (isMining && notStarted) {
21-
setAnimationState('start');
25+
// Debounce animation state changes
26+
const timer = setTimeout(() => {
27+
if (isLatestEffect) {
28+
setAnimationState('start');
29+
}
30+
}, 300);
31+
return () => {
32+
clearTimeout(timer);
33+
isLatestEffect = false;
34+
};
2235
}
23-
}, [statusIndex, isMining]);
36+
}, [indexTrigger, isMining, visualMode, visualModeToggleLoading]);
2437

2538
useEffect(() => {
26-
const notStopped = window?.glApp?.stateManager?.status !== 'not-started';
39+
let isLatestEffect = true;
40+
if (!visualMode || visualModeToggleLoading) return;
41+
const notStopped = animationStatus !== 'not-started';
2742
const preventStop = !setupComplete || isMiningInitiated || isChangingMode;
2843
const shouldStop = !isMining && notStopped && !preventStop;
2944
if (shouldStop) {
30-
setAnimationState('stop');
45+
// Debounce animation state changes
46+
const timer = setTimeout(() => {
47+
if (isLatestEffect) {
48+
setAnimationState('stop');
49+
}
50+
}, 300);
51+
return () => {
52+
clearTimeout(timer);
53+
isLatestEffect = false;
54+
};
3155
}
32-
}, [statusIndex, setupComplete, isMiningInitiated, isMining, isChangingMode]);
56+
}, [indexTrigger, setupComplete, isMiningInitiated, isMining, isChangingMode, visualMode, visualModeToggleLoading]);
3357
};

src/main.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ import { StrictMode } from 'react';
33
import { createRoot } from 'react-dom/client';
44
import AppWrapper from './App/AppWrapper.tsx';
55

6-
const root = createRoot(document.getElementById('root') as HTMLElement);
6+
document.addEventListener('DOMContentLoaded', () => {
7+
if (!window.WebGL2RenderingContext && !window.WebGLRenderingContext) {
8+
console.error('WebGL not supported!');
9+
}
10+
});
711

12+
const root = createRoot(document.getElementById('root') as HTMLElement);
813
root.render(
914
<StrictMode>
1015
<AppWrapper />

0 commit comments

Comments
 (0)