mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 09:33:10 -07:00
fix some dark mode issues, still battling the terminal to display wget progress displays
This commit is contained in:
parent
86d38819bb
commit
8ccd9595f5
5 changed files with 52 additions and 114 deletions
|
|
@ -88,7 +88,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/core": "^8.2.7",
|
"@mantine/core": "^8.2.7",
|
||||||
"@mantine/hooks": "^8.2.7",
|
"@mantine/hooks": "^8.2.7",
|
||||||
"ansi-to-html": "^0.7.2",
|
|
||||||
"execa": "^9.6.0",
|
"execa": "^9.6.0",
|
||||||
"got": "^14.4.7",
|
"got": "^14.4.7",
|
||||||
"lucide-react": "^0.541.0",
|
"lucide-react": "^0.541.0",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
Loader,
|
Loader,
|
||||||
Progress,
|
Progress,
|
||||||
rem,
|
rem,
|
||||||
|
useComputedColorScheme,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Download } from 'lucide-react';
|
import { Download } from 'lucide-react';
|
||||||
import { MouseEvent } from 'react';
|
import { MouseEvent } from 'react';
|
||||||
|
|
@ -46,6 +47,10 @@ export const DownloadCard = ({
|
||||||
onMakeCurrent,
|
onMakeCurrent,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
}: DownloadCardProps) => {
|
}: DownloadCardProps) => {
|
||||||
|
const computedColorScheme = useComputedColorScheme('light', {
|
||||||
|
getInitialValueInEffect: false,
|
||||||
|
});
|
||||||
|
const isDark = computedColorScheme === 'dark';
|
||||||
const renderActionButton = () => {
|
const renderActionButton = () => {
|
||||||
if (hasUpdate && onUpdate) {
|
if (hasUpdate && onUpdate) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -107,9 +112,8 @@ export const DownloadCard = ({
|
||||||
radius="sm"
|
radius="sm"
|
||||||
padding="sm"
|
padding="sm"
|
||||||
{...(isCurrent && {
|
{...(isCurrent && {
|
||||||
c: 'blue',
|
bg: isDark ? 'dark.6' : 'gray.0',
|
||||||
bg: 'blue.0',
|
bd: `2px solid var(--mantine-color-${isDark ? 'blue-4' : 'blue-6'})`,
|
||||||
bd: '2px solid blue',
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Group justify="space-between" align="center">
|
<Group justify="space-between" align="center">
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
Text,
|
Text,
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
useMantineColorScheme,
|
useComputedColorScheme,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { ChevronDown } from 'lucide-react';
|
import { ChevronDown } from 'lucide-react';
|
||||||
import Convert from 'ansi-to-html';
|
|
||||||
import styles from '@/styles/layout.module.css';
|
import styles from '@/styles/layout.module.css';
|
||||||
import { UI } from '@/constants';
|
import { UI } from '@/constants';
|
||||||
|
|
||||||
|
|
@ -39,19 +38,20 @@ const handleCarriageReturns = (
|
||||||
} else {
|
} else {
|
||||||
const lines = result.split('\n');
|
const lines = result.split('\n');
|
||||||
if (lines.length > 0) {
|
if (lines.length > 0) {
|
||||||
const lastLineIndex = lines.length - 1;
|
|
||||||
const restOfData = newData.slice(i + 1);
|
const restOfData = newData.slice(i + 1);
|
||||||
const nextCrOrLfIndex = restOfData.search(/[\r\n]/);
|
const nextNewlinePos = restOfData.indexOf('\n');
|
||||||
|
const replacementText =
|
||||||
|
nextNewlinePos === -1
|
||||||
|
? restOfData
|
||||||
|
: restOfData.slice(0, nextNewlinePos);
|
||||||
|
|
||||||
if (nextCrOrLfIndex === -1) {
|
lines[lines.length - 1] = replacementText;
|
||||||
lines[lastLineIndex] = restOfData;
|
result = lines.join('\n');
|
||||||
result = lines.join('\n');
|
|
||||||
break;
|
i += 1 + replacementText.length;
|
||||||
} else {
|
if (nextNewlinePos !== -1) {
|
||||||
const replacement = restOfData.slice(0, nextCrOrLfIndex);
|
result += '\n';
|
||||||
lines[lastLineIndex] = replacement;
|
i += 1;
|
||||||
result = lines.join('\n');
|
|
||||||
i += 1 + nextCrOrLfIndex;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -64,64 +64,24 @@ const handleCarriageReturns = (
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch {
|
} catch (error) {
|
||||||
|
window.electronAPI.logs.logError('Terminal CR Error', error as Error);
|
||||||
return prevContent + newData;
|
return prevContent + newData;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TerminalTab = ({ onServerReady }: TerminalTabProps) => {
|
export const TerminalTab = ({ onServerReady }: TerminalTabProps) => {
|
||||||
const { colorScheme } = useMantineColorScheme();
|
const computedColorScheme = useComputedColorScheme('light', {
|
||||||
|
getInitialValueInEffect: false,
|
||||||
|
});
|
||||||
const [terminalContent, setTerminalContent] = useState<string>('');
|
const [terminalContent, setTerminalContent] = useState<string>('');
|
||||||
const [formattedContent, setFormattedContent] = useState<string>('');
|
|
||||||
const [isUserScrolling, setIsUserScrolling] = useState<boolean>(false);
|
const [isUserScrolling, setIsUserScrolling] = useState<boolean>(false);
|
||||||
const [shouldAutoScroll, setShouldAutoScroll] = useState<boolean>(true);
|
const [shouldAutoScroll, setShouldAutoScroll] = useState<boolean>(true);
|
||||||
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
||||||
const viewportRef = useRef<HTMLDivElement>(null);
|
const viewportRef = useRef<HTMLDivElement>(null);
|
||||||
const lastScrollTop = useRef<number>(0);
|
const lastScrollTop = useRef<number>(0);
|
||||||
const updateTimeoutRef = useRef<number | null>(null);
|
|
||||||
const pendingContentRef = useRef<string>('');
|
|
||||||
|
|
||||||
const debouncedUpdateContent = useCallback((newContent: string) => {
|
const isDark = computedColorScheme === 'dark';
|
||||||
pendingContentRef.current = newContent;
|
|
||||||
|
|
||||||
if (updateTimeoutRef.current) {
|
|
||||||
clearTimeout(updateTimeoutRef.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTimeoutRef.current = window.setTimeout(() => {
|
|
||||||
setTerminalContent(pendingContentRef.current);
|
|
||||||
updateTimeoutRef.current = null;
|
|
||||||
}, 16);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const converter = useRef(
|
|
||||||
new Convert({
|
|
||||||
fg: colorScheme === 'dark' ? '#ffffff' : '#000000',
|
|
||||||
bg: colorScheme === 'dark' ? '#1a1b1e' : '#ffffff',
|
|
||||||
newline: false,
|
|
||||||
escapeXML: true,
|
|
||||||
stream: false,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
converter.current = new Convert({
|
|
||||||
fg: colorScheme === 'dark' ? '#ffffff' : '#000000',
|
|
||||||
bg: colorScheme === 'dark' ? '#1a1b1e' : '#ffffff',
|
|
||||||
newline: false,
|
|
||||||
escapeXML: true,
|
|
||||||
stream: false,
|
|
||||||
});
|
|
||||||
if (terminalContent) {
|
|
||||||
setFormattedContent(converter.current.toHtml(terminalContent));
|
|
||||||
}
|
|
||||||
}, [colorScheme, terminalContent]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (terminalContent) {
|
|
||||||
setFormattedContent(converter.current.toHtml(terminalContent));
|
|
||||||
}
|
|
||||||
}, [terminalContent]);
|
|
||||||
|
|
||||||
const handleScroll = ({ y }: { y: number }) => {
|
const handleScroll = ({ y }: { y: number }) => {
|
||||||
if (!viewportRef.current) return;
|
if (!viewportRef.current) return;
|
||||||
|
|
@ -145,7 +105,7 @@ export const TerminalTab = ({ onServerReady }: TerminalTabProps) => {
|
||||||
const viewport = viewportRef.current;
|
const viewport = viewportRef.current;
|
||||||
viewport.scrollTop = viewport.scrollHeight;
|
viewport.scrollTop = viewport.scrollHeight;
|
||||||
}
|
}
|
||||||
}, [formattedContent, shouldAutoScroll, isUserScrolling]);
|
}, [terminalContent, shouldAutoScroll, isUserScrolling]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const cleanup = window.electronAPI.kobold.onKoboldOutput((data: string) => {
|
const cleanup = window.electronAPI.kobold.onKoboldOutput((data: string) => {
|
||||||
|
|
@ -165,19 +125,12 @@ export const TerminalTab = ({ onServerReady }: TerminalTabProps) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newContent = handleCarriageReturns(prev, newData);
|
return handleCarriageReturns(prev, newData);
|
||||||
|
|
||||||
if (newData.includes('\r') && !newData.includes('\n')) {
|
|
||||||
debouncedUpdateContent(newContent);
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newContent;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return cleanup;
|
return cleanup;
|
||||||
}, [onServerReady, debouncedUpdateContent]);
|
}, [onServerReady]);
|
||||||
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
if (viewportRef.current) {
|
if (viewportRef.current) {
|
||||||
|
|
@ -194,10 +147,9 @@ export const TerminalTab = ({ onServerReady }: TerminalTabProps) => {
|
||||||
height: `calc(100vh - ${UI.HEADER_HEIGHT}px)`,
|
height: `calc(100vh - ${UI.HEADER_HEIGHT}px)`,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
backgroundColor:
|
backgroundColor: isDark
|
||||||
colorScheme === 'dark'
|
? 'var(--mantine-color-dark-filled)'
|
||||||
? 'var(--mantine-color-dark-filled)'
|
: 'var(--mantine-color-gray-0)',
|
||||||
: 'var(--mantine-color-gray-0)',
|
|
||||||
borderRadius: 'inherit',
|
borderRadius: 'inherit',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
|
|
@ -219,18 +171,19 @@ export const TerminalTab = ({ onServerReady }: TerminalTabProps) => {
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
fontFamily: 'inherit',
|
fontFamily:
|
||||||
fontSize: 'inherit',
|
'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||||
lineHeight: 'inherit',
|
fontSize: '14px',
|
||||||
color:
|
lineHeight: 1.4,
|
||||||
colorScheme === 'dark'
|
color: isDark
|
||||||
? 'var(--mantine-color-gray-0)'
|
? 'var(--mantine-color-gray-0)'
|
||||||
: 'var(--mantine-color-dark-filled)',
|
: 'var(--mantine-color-dark-filled)',
|
||||||
whiteSpace: 'pre-wrap',
|
whiteSpace: 'pre-wrap',
|
||||||
wordBreak: 'break-word',
|
wordBreak: 'break-word',
|
||||||
}}
|
}}
|
||||||
dangerouslySetInnerHTML={{ __html: formattedContent }}
|
>
|
||||||
/>
|
{terminalContent}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
import { Stack, Text, Group, SegmentedControl, rem } from '@mantine/core';
|
import { Stack, Text, Group, SegmentedControl, rem } from '@mantine/core';
|
||||||
import { useMantineColorScheme } from '@mantine/core';
|
import { useMantineColorScheme, useComputedColorScheme } from '@mantine/core';
|
||||||
import { Sun, Moon, Monitor } from 'lucide-react';
|
import { Sun, Moon, Monitor } from 'lucide-react';
|
||||||
|
|
||||||
export const AppearanceTab = () => {
|
export const AppearanceTab = () => {
|
||||||
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
||||||
|
const computedColorScheme = useComputedColorScheme('light', {
|
||||||
|
getInitialValueInEffect: false,
|
||||||
|
});
|
||||||
|
const isDark = computedColorScheme === 'dark';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg" h="100%">
|
<Stack gap="lg" h="100%">
|
||||||
|
|
@ -22,14 +26,11 @@ export const AppearanceTab = () => {
|
||||||
}
|
}
|
||||||
styles={(theme) => ({
|
styles={(theme) => ({
|
||||||
indicator: {
|
indicator: {
|
||||||
backgroundColor:
|
backgroundColor: isDark
|
||||||
colorScheme === 'dark'
|
? theme.colors.dark[5]
|
||||||
? theme.colors.dark[5]
|
: theme.colors.gray[2],
|
||||||
: theme.colors.gray[2],
|
|
||||||
border: `1px solid ${
|
border: `1px solid ${
|
||||||
colorScheme === 'dark'
|
isDark ? theme.colors.dark[4] : theme.colors.gray[4]
|
||||||
? theme.colors.dark[4]
|
|
||||||
: theme.colors.gray[4]
|
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
19
yarn.lock
19
yarn.lock
|
|
@ -2233,17 +2233,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ansi-to-html@npm:^0.7.2":
|
|
||||||
version: 0.7.2
|
|
||||||
resolution: "ansi-to-html@npm:0.7.2"
|
|
||||||
dependencies:
|
|
||||||
entities: "npm:^2.2.0"
|
|
||||||
bin:
|
|
||||||
ansi-to-html: bin/ansi-to-html
|
|
||||||
checksum: 10c0/031da78f716e7c6b0e391c64f7bc5e95f2d37123dcc3237d8c592dc35830dd0da05e0c3f3e3f8179856cfe5fd85c689d2ad85024b71b50014da9ef6e8fa021cf
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"app-builder-bin@npm:5.0.0-alpha.12":
|
"app-builder-bin@npm:5.0.0-alpha.12":
|
||||||
version: 5.0.0-alpha.12
|
version: 5.0.0-alpha.12
|
||||||
resolution: "app-builder-bin@npm:5.0.0-alpha.12"
|
resolution: "app-builder-bin@npm:5.0.0-alpha.12"
|
||||||
|
|
@ -3603,13 +3592,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"entities@npm:^2.2.0":
|
|
||||||
version: 2.2.0
|
|
||||||
resolution: "entities@npm:2.2.0"
|
|
||||||
checksum: 10c0/7fba6af1f116300d2ba1c5673fc218af1961b20908638391b4e1e6d5850314ee2ac3ec22d741b3a8060479911c99305164aed19b6254bde75e7e6b1b2c3f3aa3
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"env-paths@npm:^2.2.0":
|
"env-paths@npm:^2.2.0":
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
resolution: "env-paths@npm:2.2.1"
|
resolution: "env-paths@npm:2.2.1"
|
||||||
|
|
@ -4409,7 +4391,6 @@ __metadata:
|
||||||
"@typescript-eslint/eslint-plugin": "npm:^8.40.0"
|
"@typescript-eslint/eslint-plugin": "npm:^8.40.0"
|
||||||
"@typescript-eslint/parser": "npm:^8.40.0"
|
"@typescript-eslint/parser": "npm:^8.40.0"
|
||||||
"@vitejs/plugin-react": "npm:^5.0.1"
|
"@vitejs/plugin-react": "npm:^5.0.1"
|
||||||
ansi-to-html: "npm:^0.7.2"
|
|
||||||
cross-env: "npm:^10.0.0"
|
cross-env: "npm:^10.0.0"
|
||||||
cspell: "npm:^9.2.0"
|
cspell: "npm:^9.2.0"
|
||||||
electron: "npm:^37.3.1"
|
electron: "npm:^37.3.1"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue