Make engine background color driven by theme
setting (#1842)
* Bump ts lib * Make engine background color driven by theme setting * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Force snapshots to dark mode, fix theme init * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Don't assume we have engineCommandManager in CameraControls, because for some reason it's being loaded before engineConnection in test environments? * Merge branch 'main' into change-bg-color * Replace optional chaining with this.engineCommandManager * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Okay now all snapshot tests are actually in dark mode * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * trigger ci --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
@ -22,7 +22,7 @@ test.beforeEach(async ({ context, page }) => {
|
|||||||
onboardingStatus: 'dismissed',
|
onboardingStatus: 'dismissed',
|
||||||
showDebugPanel: true,
|
showDebugPanel: true,
|
||||||
textWrapping: 'On',
|
textWrapping: 'On',
|
||||||
theme: 'system',
|
theme: 'dark',
|
||||||
unitSystem: 'imperial',
|
unitSystem: 'imperial',
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -397,7 +397,7 @@ test('Draft segments should look right', async ({ page, context }) => {
|
|||||||
onboardingStatus: 'dismissed',
|
onboardingStatus: 'dismissed',
|
||||||
showDebugPanel: true,
|
showDebugPanel: true,
|
||||||
textWrapping: 'On',
|
textWrapping: 'On',
|
||||||
theme: 'system',
|
theme: 'dark',
|
||||||
unitSystem: 'imperial',
|
unitSystem: 'imperial',
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -475,7 +475,7 @@ test('Client side scene scale should match engine scale inch', async ({
|
|||||||
onboardingStatus: 'dismissed',
|
onboardingStatus: 'dismissed',
|
||||||
showDebugPanel: true,
|
showDebugPanel: true,
|
||||||
textWrapping: 'On',
|
textWrapping: 'On',
|
||||||
theme: 'system',
|
theme: 'dark',
|
||||||
unitSystem: 'imperial',
|
unitSystem: 'imperial',
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -575,7 +575,7 @@ test('Client side scene scale should match engine scale mm', async ({
|
|||||||
onboardingStatus: 'dismissed',
|
onboardingStatus: 'dismissed',
|
||||||
showDebugPanel: true,
|
showDebugPanel: true,
|
||||||
textWrapping: 'On',
|
textWrapping: 'On',
|
||||||
theme: 'system',
|
theme: 'dark',
|
||||||
unitSystem: 'metric',
|
unitSystem: 'metric',
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
@ -10,7 +10,7 @@
|
|||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@headlessui/react": "^1.7.18",
|
"@headlessui/react": "^1.7.18",
|
||||||
"@headlessui/tailwindcss": "^0.2.0",
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
"@kittycad/lib": "^0.0.55",
|
"@kittycad/lib": "^0.1.0",
|
||||||
"@lezer/javascript": "^1.4.9",
|
"@lezer/javascript": "^1.4.9",
|
||||||
"@open-rpc/client-js": "^1.8.1",
|
"@open-rpc/client-js": "^1.8.1",
|
||||||
"@react-hook/resize-observer": "^1.2.6",
|
"@react-hook/resize-observer": "^1.2.6",
|
||||||
|
@ -265,15 +265,15 @@ export class CameraControls {
|
|||||||
this.onCameraChange()
|
this.onCameraChange()
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
engineCommandManager.subscribeTo({
|
this.engineCommandManager.subscribeTo({
|
||||||
event: 'camera_drag_end',
|
event: 'camera_drag_end',
|
||||||
callback: cb,
|
callback: cb,
|
||||||
})
|
})
|
||||||
engineCommandManager.subscribeTo({
|
this.engineCommandManager.subscribeTo({
|
||||||
event: 'default_camera_zoom',
|
event: 'default_camera_zoom',
|
||||||
callback: cb,
|
callback: cb,
|
||||||
})
|
})
|
||||||
engineCommandManager.subscribeTo({
|
this.engineCommandManager.subscribeTo({
|
||||||
event: 'default_camera_get_settings',
|
event: 'default_camera_get_settings',
|
||||||
callback: cb,
|
callback: cb,
|
||||||
})
|
})
|
||||||
|
@ -66,13 +66,13 @@ export const ModelingMachineProvider = ({
|
|||||||
const {
|
const {
|
||||||
auth,
|
auth,
|
||||||
settings: {
|
settings: {
|
||||||
context: { baseUnit },
|
context: { baseUnit, theme },
|
||||||
},
|
},
|
||||||
} = useSettingsAuthContext()
|
} = useSettingsAuthContext()
|
||||||
const { code } = useKclContext()
|
const { code } = useKclContext()
|
||||||
const token = auth?.context?.token
|
const token = auth?.context?.token
|
||||||
const streamRef = useRef<HTMLDivElement>(null)
|
const streamRef = useRef<HTMLDivElement>(null)
|
||||||
useSetupEngineManager(streamRef, token)
|
useSetupEngineManager(streamRef, token, theme)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isShiftDown,
|
isShiftDown,
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
validateSettings,
|
validateSettings,
|
||||||
} from 'lib/settings/settingsUtils'
|
} from 'lib/settings/settingsUtils'
|
||||||
import { toast } from 'react-hot-toast'
|
import { toast } from 'react-hot-toast'
|
||||||
import { setThemeClass, Themes } from 'lib/theme'
|
import { getThemeColorForEngine, setThemeClass, Themes } from 'lib/theme'
|
||||||
import {
|
import {
|
||||||
AnyStateMachine,
|
AnyStateMachine,
|
||||||
ContextFrom,
|
ContextFrom,
|
||||||
@ -22,7 +22,8 @@ import {
|
|||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { settingsCommandBarConfig } from 'lib/commandBarConfigs/settingsCommandConfig'
|
import { settingsCommandBarConfig } from 'lib/commandBarConfigs/settingsCommandConfig'
|
||||||
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
||||||
import { kclManager, sceneInfra } from 'lib/singletons'
|
import { kclManager, sceneInfra, engineCommandManager } from 'lib/singletons'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
type MachineContext<T extends AnyStateMachine> = {
|
type MachineContext<T extends AnyStateMachine> = {
|
||||||
state: StateFrom<T>
|
state: StateFrom<T>
|
||||||
@ -95,6 +96,16 @@ export const SettingsAuthProviderBase = ({
|
|||||||
: context.baseUnit
|
: context.baseUnit
|
||||||
sceneInfra.baseUnit = newBaseUnit
|
sceneInfra.baseUnit = newBaseUnit
|
||||||
},
|
},
|
||||||
|
setEngineTheme: (context) => {
|
||||||
|
engineCommandManager.sendSceneCommand({
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'set_background_color',
|
||||||
|
color: getThemeColorForEngine(context.theme),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
toastSuccess: (context, event) => {
|
toastSuccess: (context, event) => {
|
||||||
const truncatedNewValue =
|
const truncatedNewValue =
|
||||||
'data' in event && event.data instanceof Object
|
'data' in event && event.data instanceof Object
|
||||||
|
@ -3,10 +3,12 @@ import { parse } from '../lang/wasm'
|
|||||||
import { useStore } from '../useStore'
|
import { useStore } from '../useStore'
|
||||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||||
import { deferExecution } from 'lib/utils'
|
import { deferExecution } from 'lib/utils'
|
||||||
|
import { Themes } from 'lib/theme'
|
||||||
|
|
||||||
export function useSetupEngineManager(
|
export function useSetupEngineManager(
|
||||||
streamRef: React.RefObject<HTMLDivElement>,
|
streamRef: React.RefObject<HTMLDivElement>,
|
||||||
token?: string
|
token?: string,
|
||||||
|
theme = Themes.System
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
setMediaStream,
|
setMediaStream,
|
||||||
@ -43,6 +45,7 @@ export function useSetupEngineManager(
|
|||||||
return kclManager.executeAst(_ast, true)
|
return kclManager.executeAst(_ast, true)
|
||||||
},
|
},
|
||||||
token,
|
token,
|
||||||
|
theme,
|
||||||
})
|
})
|
||||||
setStreamDimensions({
|
setStreamDimensions({
|
||||||
streamWidth: quadWidth,
|
streamWidth: quadWidth,
|
||||||
|
@ -4,6 +4,7 @@ import { Models } from '@kittycad/lib'
|
|||||||
import { exportSave } from 'lib/exportSave'
|
import { exportSave } from 'lib/exportSave'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
||||||
|
import { Themes, getThemeColorForEngine } from 'lib/theme'
|
||||||
|
|
||||||
let lastMessage = ''
|
let lastMessage = ''
|
||||||
|
|
||||||
@ -887,6 +888,7 @@ export class EngineCommandManager {
|
|||||||
height,
|
height,
|
||||||
executeCode,
|
executeCode,
|
||||||
token,
|
token,
|
||||||
|
theme = Themes.Dark,
|
||||||
}: {
|
}: {
|
||||||
setMediaStream: (stream: MediaStream) => void
|
setMediaStream: (stream: MediaStream) => void
|
||||||
setIsStreamReady: (isStreamReady: boolean) => void
|
setIsStreamReady: (isStreamReady: boolean) => void
|
||||||
@ -894,6 +896,7 @@ export class EngineCommandManager {
|
|||||||
height: number
|
height: number
|
||||||
executeCode: (code?: string, force?: boolean) => void
|
executeCode: (code?: string, force?: boolean) => void
|
||||||
token?: string
|
token?: string
|
||||||
|
theme?: Themes
|
||||||
}) {
|
}) {
|
||||||
if (width === 0 || height === 0) {
|
if (width === 0 || height === 0) {
|
||||||
return
|
return
|
||||||
@ -919,6 +922,19 @@ export class EngineCommandManager {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onEngineConnectionOpen: () => {
|
onEngineConnectionOpen: () => {
|
||||||
|
// Set the stream background color
|
||||||
|
// This takes RGBA values from 0-1
|
||||||
|
// So we convert from the conventional 0-255 found in Figma
|
||||||
|
|
||||||
|
this.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'set_background_color',
|
||||||
|
color: getThemeColorForEngine(theme),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// Make the axis gizmo.
|
// Make the axis gizmo.
|
||||||
// We do this after the connection opened to avoid a race condition.
|
// We do this after the connection opened to avoid a race condition.
|
||||||
// Connected opened is the last thing that happens when the stream
|
// Connected opened is the last thing that happens when the stream
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
EngineCommand,
|
EngineCommand,
|
||||||
} from '../lang/std/engineConnection'
|
} from '../lang/std/engineConnection'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
|
import { Themes } from './theme'
|
||||||
|
|
||||||
type WebSocketResponse = Models['OkWebSocketResponseData_type']
|
type WebSocketResponse = Models['OkWebSocketResponseData_type']
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ export async function executor(
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
executeCode: () => {},
|
executeCode: () => {},
|
||||||
|
theme: Themes.Dark,
|
||||||
})
|
})
|
||||||
await engineCommandManager.waitForReady
|
await engineCommandManager.waitForReady
|
||||||
engineCommandManager.startNewSession()
|
engineCommandManager.startNewSession()
|
||||||
|
@ -6,7 +6,8 @@ export enum Themes {
|
|||||||
|
|
||||||
// Get the theme from the system settings manually
|
// Get the theme from the system settings manually
|
||||||
export function getSystemTheme(): Exclude<Themes, 'system'> {
|
export function getSystemTheme(): Exclude<Themes, 'system'> {
|
||||||
return typeof window !== 'undefined' && 'matchMedia' in window
|
return typeof globalThis.window !== 'undefined' &&
|
||||||
|
'matchMedia' in globalThis.window
|
||||||
? window.matchMedia('(prefers-color-scheme: dark)').matches
|
? window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
? Themes.Dark
|
? Themes.Dark
|
||||||
: Themes.Light
|
: Themes.Light
|
||||||
@ -21,3 +22,12 @@ export function setThemeClass(theme: Themes) {
|
|||||||
document.body.classList.remove('dark')
|
document.body.classList.remove('dark')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getThemeColorForEngine(theme: Themes) {
|
||||||
|
const resolvedTheme = theme === Themes.System ? getSystemTheme() : theme
|
||||||
|
const dark = 28 / 255
|
||||||
|
const light = 242 / 255
|
||||||
|
return resolvedTheme === Themes.Dark
|
||||||
|
? { r: dark, g: dark, b: dark, a: 1 }
|
||||||
|
: { r: light, g: light, b: light, a: 1 }
|
||||||
|
}
|
||||||
|
@ -112,6 +112,7 @@ export const settingsMachine = createMachine(
|
|||||||
'persistSettings',
|
'persistSettings',
|
||||||
'toastSuccess',
|
'toastSuccess',
|
||||||
'setThemeClass',
|
'setThemeClass',
|
||||||
|
'setEngineTheme',
|
||||||
],
|
],
|
||||||
target: 'idle',
|
target: 'idle',
|
||||||
internal: true,
|
internal: true,
|
||||||
|
@ -1802,10 +1802,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||||
|
|
||||||
"@kittycad/lib@^0.0.55":
|
"@kittycad/lib@^0.1.0":
|
||||||
version "0.0.55"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.55.tgz#7fe327bb8c55422d7d233b5982a35eb32095d44b"
|
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.1.0.tgz#1a65936cd4f933bbea5a691f195f6eb63f1c14b2"
|
||||||
integrity sha512-Xvs7WJqW/U2VG5MSKjUx8uDY7e9Wibq/zpfXVef26+b1W0OS0A6MZOXAMmHwDVuAYWuHDdgPa/Hg8NGK1GXd1g==
|
integrity sha512-Zx7ukUDIJSoDowMII+j5WU8FqcYaOA3HqtG6dNwSiv4+MdU+Ifuj+XjduqxUxP0Z4eaq4u6hV8lBsv4b4CYzeA==
|
||||||
dependencies:
|
dependencies:
|
||||||
node-fetch "3.3.2"
|
node-fetch "3.3.2"
|
||||||
openapi-types "^12.0.0"
|
openapi-types "^12.0.0"
|
||||||
|