mirror of
https://github.com/lobehub/sd-webui-lobe-theme.git
synced 2026-01-09 06:23:44 +08:00
🐛 fix(split-view): Fix split view
This commit is contained in:
parent
c320ec2982
commit
f1d5ab205e
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@ -47,6 +47,12 @@ jobs:
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Git add
|
||||
run: git add -f javascript/main.js
|
||||
|
||||
- name: Release
|
||||
id: release
|
||||
run: pnpm run release
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -43,4 +43,3 @@ test-output
|
||||
__pycache__
|
||||
/lobe_theme_config.json
|
||||
/javascript/*.js
|
||||
!/javascript/main.js
|
||||
|
||||
@ -55,6 +55,7 @@ Dockerfile*
|
||||
|
||||
# misc
|
||||
# add other ignore file below
|
||||
*.py
|
||||
style.css
|
||||
javascript/
|
||||
.stylelintignore
|
||||
|
||||
File diff suppressed because one or more lines are too long
34
src/pages/Content/SplitView.tsx
Normal file
34
src/pages/Content/SplitView.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { memo, useEffect } from 'react';
|
||||
|
||||
const Preview = memo(() => {
|
||||
useEffect(() => {
|
||||
console.time('🤯 [layout] inject - Split Previewer');
|
||||
// tab_txt2img
|
||||
const txt2imgToprow = gradioApp().querySelector('#txt2img_toprow') as HTMLDivElement;
|
||||
const txt2imgSettings = gradioApp().querySelector('#txt2img_settings') as HTMLDivElement;
|
||||
const txt2imgGenerate = gradioApp().querySelector('#txt2img_generate') as HTMLButtonElement;
|
||||
const txt2imgPreview = gradioApp().querySelector(
|
||||
'#txt2img_gallery_container',
|
||||
) as HTMLDivElement;
|
||||
if (txt2imgToprow && txt2imgSettings && txt2imgGenerate && txt2imgPreview) {
|
||||
txt2imgSettings.prepend(txt2imgToprow);
|
||||
txt2imgPreview.prepend(txt2imgGenerate);
|
||||
}
|
||||
// tab_img2img
|
||||
const img2imgToprow = gradioApp().querySelector('#img2img_toprow') as HTMLDivElement;
|
||||
const img2imgSettings = gradioApp().querySelector('#img2img_settings') as HTMLDivElement;
|
||||
const img2imgGenerate = gradioApp().querySelector('#img2img_generate') as HTMLButtonElement;
|
||||
const img2imgPreview = gradioApp().querySelector(
|
||||
'#img2img_gallery_container',
|
||||
) as HTMLDivElement;
|
||||
if (img2imgSettings && img2imgToprow && img2imgGenerate && img2imgPreview) {
|
||||
img2imgSettings.prepend(img2imgToprow);
|
||||
img2imgPreview.prepend(img2imgGenerate);
|
||||
}
|
||||
console.timeEnd('🤯 [layout] inject - Split Previewer');
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
export default Preview;
|
||||
@ -1,3 +1,4 @@
|
||||
import { useResponsive } from 'antd-style';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { memo, useEffect, useRef } from 'react';
|
||||
|
||||
@ -5,10 +6,12 @@ import formatPrompt from '@/script/formatPrompt';
|
||||
import { selectors, useAppStore } from '@/store';
|
||||
import { type DivProps } from '@/types';
|
||||
|
||||
import SplitView from './SplitView';
|
||||
import { useStyles } from './style';
|
||||
|
||||
const Content = memo<DivProps>(({ className, ...props }) => {
|
||||
const mainReference = useRef<HTMLDivElement>(null);
|
||||
const { mobile } = useResponsive();
|
||||
const setting = useAppStore(selectors.currentSetting, isEqual);
|
||||
|
||||
const { cx, styles } = useStyles({
|
||||
@ -49,17 +52,20 @@ const Content = memo<DivProps>(({ className, ...props }) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(
|
||||
styles.container,
|
||||
styles.textares,
|
||||
styles.text2img,
|
||||
setting.layoutSplitPreview && styles.splitView,
|
||||
className,
|
||||
)}
|
||||
ref={mainReference}
|
||||
{...props}
|
||||
/>
|
||||
<>
|
||||
<div
|
||||
className={cx(
|
||||
styles.container,
|
||||
styles.textares,
|
||||
styles.text2img,
|
||||
setting.layoutSplitPreview && styles.splitView,
|
||||
className,
|
||||
)}
|
||||
ref={mainReference}
|
||||
{...props}
|
||||
/>
|
||||
{setting.layoutSplitPreview && mobile === false && <SplitView />}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -27,6 +27,12 @@ export const useStyles = createStyles(
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#txt2img_results,
|
||||
#img2img_results {
|
||||
padding: 0 !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
#txt2img_render,
|
||||
#img2img_render {
|
||||
display: block !important;
|
||||
@ -62,28 +68,15 @@ export const useStyles = createStyles(
|
||||
}
|
||||
`,
|
||||
splitView: css`
|
||||
#txt2img_generate,
|
||||
#img2img_generate {
|
||||
border-radius: ${token.borderRadius}px !important;
|
||||
}
|
||||
|
||||
#txt2img_toprow,
|
||||
#img2img_toprow {
|
||||
flex-direction: column;
|
||||
padding: 0 !important;
|
||||
background: transparent !important;
|
||||
|
||||
.interrogate-col {
|
||||
flex-direction: row;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#txt2img_actions_column,
|
||||
#img2img_actions_column {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
#txt2img_styles_row,
|
||||
#img2img_styles_row {
|
||||
padding: 16px;
|
||||
background: ${token.colorBgContainer};
|
||||
border-radius: ${token.borderRadius}px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
text2img: css`
|
||||
@ -155,6 +148,7 @@ export const useStyles = createStyles(
|
||||
padding: 16px !important;
|
||||
|
||||
background-color: ${token.colorBgContainer}!important;
|
||||
border: 1px solid ${token.colorBorderSecondary} !important;
|
||||
border-radius: ${token.borderRadius}px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
import { DraggablePanel, LayoutSidebarInner } from '@lobehub/ui';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { memo, useEffect, useRef } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { selectors, useAppStore } from '@/store';
|
||||
import { type DivProps } from '@/types';
|
||||
|
||||
import { useStyles } from './style';
|
||||
|
||||
export interface PreviewProps extends DivProps {
|
||||
headerHeight: number;
|
||||
}
|
||||
|
||||
const Preview = memo<PreviewProps>(({ headerHeight }) => {
|
||||
const currentTab = useAppStore(selectors.currentTab, shallow);
|
||||
const setting = useAppStore(selectors.currentSetting, isEqual);
|
||||
const { cx, styles } = useStyles({
|
||||
headerHeight,
|
||||
isPrimaryColor: Boolean(setting.primaryColor),
|
||||
liteAnimation: setting.liteAnimation,
|
||||
});
|
||||
const txt2imgReference = useRef<HTMLDivElement>(null);
|
||||
const img2imgReference = useRef<HTMLDivElement>(null);
|
||||
const extras2imgReference = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
console.time('🤯 [layout] inject - Split Previewer');
|
||||
// tab_txt2img
|
||||
const txt2imgToprow = gradioApp().querySelector('#txt2img_toprow') as HTMLDivElement;
|
||||
const txt2imgSettings = gradioApp().querySelector('#txt2img_settings') as HTMLDivElement;
|
||||
if (txt2imgToprow && txt2imgSettings) {
|
||||
txt2imgSettings.prepend(txt2imgToprow);
|
||||
}
|
||||
// tab_img2img
|
||||
const img2imgToprow = gradioApp().querySelector('#img2img_toprow') as HTMLDivElement;
|
||||
const img2imgSettings = gradioApp().querySelector('#img2img_settings') as HTMLDivElement;
|
||||
if (img2imgSettings && img2imgToprow) {
|
||||
img2imgSettings.prepend(img2imgToprow);
|
||||
}
|
||||
// tab_txt2img
|
||||
const txt2imgPreview = gradioApp().querySelector('#txt2img_results') as HTMLDivElement;
|
||||
const txt2imgButton = gradioApp().querySelector('#txt2img_generate_box') as HTMLDivElement;
|
||||
if (txt2imgPreview && txt2imgButton) {
|
||||
txt2imgReference.current?.append(txt2imgButton, txt2imgPreview);
|
||||
}
|
||||
// tab_img2img
|
||||
const img2imgPreview = gradioApp().querySelector('#img2img_results') as HTMLDivElement;
|
||||
const img2imgButton = gradioApp().querySelector('#img2img_generate_box') as HTMLDivElement;
|
||||
if (img2imgPreview && img2imgButton) {
|
||||
img2imgReference.current?.append(img2imgButton, img2imgPreview);
|
||||
}
|
||||
// tab_extras
|
||||
const extrasPreview = gradioApp().querySelector('#extras_results') as HTMLDivElement;
|
||||
const extrasButton = gradioApp().querySelector('#extras_generate') as HTMLDivElement;
|
||||
if (extrasPreview && extrasButton) {
|
||||
extras2imgReference.current?.append(extrasButton, extrasPreview);
|
||||
}
|
||||
|
||||
console.timeEnd('🤯 [layout] inject - Split Previewer');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DraggablePanel
|
||||
defaultSize={{ width: '30vw' }}
|
||||
expandable={false}
|
||||
minWidth={200}
|
||||
mode="fixed"
|
||||
pin
|
||||
placement="right"
|
||||
>
|
||||
<LayoutSidebarInner>
|
||||
<div className={styles.container}>
|
||||
<div
|
||||
className={cx(styles.inner, styles.preview)}
|
||||
ref={txt2imgReference}
|
||||
style={{ display: currentTab === 'tab_txt2img' ? 'flex' : 'none' }}
|
||||
/>
|
||||
<div
|
||||
className={cx(styles.inner, styles.preview)}
|
||||
ref={img2imgReference}
|
||||
style={{ display: currentTab === 'tab_img2img' ? 'flex' : 'none' }}
|
||||
/>
|
||||
<div
|
||||
className={cx(styles.inner, styles.preview)}
|
||||
ref={extras2imgReference}
|
||||
style={{ display: currentTab === 'tab_extras' ? 'flex' : 'none' }}
|
||||
/>
|
||||
</div>
|
||||
</LayoutSidebarInner>
|
||||
</DraggablePanel>
|
||||
);
|
||||
});
|
||||
|
||||
export default Preview;
|
||||
@ -1,113 +0,0 @@
|
||||
import { createStyles } from 'antd-style';
|
||||
import { adjustHue, rgba } from 'polished';
|
||||
|
||||
export const useStyles = createStyles(
|
||||
(
|
||||
{ css, token, stylish },
|
||||
{
|
||||
headerHeight = 64,
|
||||
isPrimaryColor,
|
||||
liteAnimation,
|
||||
}: { headerHeight?: number; isPrimaryColor?: boolean; liteAnimation?: boolean },
|
||||
) => {
|
||||
const primaryGradient =
|
||||
isPrimaryColor &&
|
||||
css`
|
||||
background-image: linear-gradient(
|
||||
-45deg,
|
||||
${token.colorPrimary},
|
||||
${adjustHue(45, token.colorPrimary)},
|
||||
${token.colorPrimary},
|
||||
${adjustHue(-45, token.colorPrimary)}
|
||||
);
|
||||
`;
|
||||
return {
|
||||
container: css`
|
||||
height: calc(100vh - ${headerHeight}px);
|
||||
`,
|
||||
inner: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
height: 100%;
|
||||
padding: 16px;
|
||||
|
||||
[id$='_results'] {
|
||||
flex: 1;
|
||||
|
||||
> div:not([id$='_gallery_container']) {
|
||||
flex-grow: 0 !important;
|
||||
}
|
||||
|
||||
[id$='_gallery_container'] {
|
||||
flex-grow: 1 !important;
|
||||
}
|
||||
}
|
||||
`,
|
||||
preview: css`
|
||||
button {
|
||||
&#extras_generate {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&.svelte-1p4r00v {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.progressDiv > .progress {
|
||||
${!liteAnimation && stylish.gradientAnimation};
|
||||
${!liteAnimation && primaryGradient};
|
||||
}
|
||||
|
||||
[id$='_results'] {
|
||||
padding: 0 !important;
|
||||
background: none !important;
|
||||
|
||||
[id$='img_gallery_container'] {
|
||||
div:not(.livePreview) {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
[id$='_gallery'] {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.livePreview {
|
||||
top: 28px;
|
||||
left: 4px;
|
||||
background: ${token.colorBgElevated};
|
||||
}
|
||||
|
||||
.preview {
|
||||
max-height: unset !important;
|
||||
background: ${rgba(token.colorBgLayout, 0.5)} !important;
|
||||
}
|
||||
|
||||
.empty {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
[id^='html_info_']:has(p) {
|
||||
padding: 8px 12px;
|
||||
|
||||
font-family: ${token.fontFamilyCode};
|
||||
font-size: 12px;
|
||||
color: ${token.colorInfoText};
|
||||
|
||||
background: ${token.colorInfoBg};
|
||||
border: 1px solid ${token.colorInfoBorder};
|
||||
border-radius: ${token.borderRadius}px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.2em 0;
|
||||
text-align: unset;
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
},
|
||||
);
|
||||
@ -1,8 +1,6 @@
|
||||
import { LayoutHeader, LayoutMain, LayoutSidebar } from '@lobehub/ui';
|
||||
import { useResponsive } from 'antd-style';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { memo, useEffect } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import '@/i18n/config';
|
||||
import { PromptHighlight } from '@/modules/PromptHighlight';
|
||||
@ -14,16 +12,13 @@ import Content from './Content';
|
||||
import ExtraNetworkSidebar from './ExtraNetworkSidebar';
|
||||
import Footer from './Footer';
|
||||
import Header from './Header';
|
||||
import Preview from './Preview';
|
||||
import QuickSettingSidebar from './QuickSettingSidebar';
|
||||
import { useStyles } from './style';
|
||||
|
||||
const HEADER_HEIGHT = 64;
|
||||
|
||||
const Index = memo(() => {
|
||||
const currentTab = useAppStore(selectors.currentTab, shallow);
|
||||
const setting = useAppStore(selectors.currentSetting, isEqual);
|
||||
const { mobile } = useResponsive();
|
||||
const { cx, styles } = useStyles({
|
||||
headerHeight: HEADER_HEIGHT,
|
||||
isPrimaryColor: Boolean(setting.primaryColor),
|
||||
@ -55,20 +50,6 @@ const Index = memo(() => {
|
||||
</LayoutSidebar>
|
||||
)}
|
||||
<Content className={cx(!setting.enableSidebar && styles.quicksettings)} />
|
||||
{setting.layoutSplitPreview && mobile === false && (
|
||||
<LayoutSidebar
|
||||
className={cx(styles.sidebar, styles.panel)}
|
||||
headerHeight={HEADER_HEIGHT}
|
||||
style={{
|
||||
display: ['tab_txt2img', 'tab_img2img', 'tab_extras'].includes(currentTab) ?
|
||||
'block' :
|
||||
'none',
|
||||
flex: 0,
|
||||
}}
|
||||
>
|
||||
<Preview headerHeight={HEADER_HEIGHT} />
|
||||
</LayoutSidebar>
|
||||
)}
|
||||
{setting?.enableExtraNetworkSidebar && (
|
||||
<LayoutSidebar
|
||||
className={styles.sidebar}
|
||||
|
||||
@ -91,19 +91,19 @@ const updateCardForCivitai = () => {
|
||||
metadataButton = card.querySelector('.metadata-button');
|
||||
// Additional node
|
||||
additionalNode = card.querySelector('.actions .additional');
|
||||
|
||||
|
||||
// Get ul node, which is the parent of all buttons
|
||||
ulNode = card.querySelector('.actions .additional ul');
|
||||
if (ulNode == null) {
|
||||
ulNode = document.createElement("ul");
|
||||
additionalNode.appendChild(ulNode);
|
||||
if (ulNode === undefined) {
|
||||
ulNode = document.createElement('ul');
|
||||
additionalNode.append(ulNode);
|
||||
}
|
||||
|
||||
// Replace preview text button
|
||||
replacePreviewButton = card.querySelector('.actions .additional a');
|
||||
if (replacePreviewButton == null) {
|
||||
replacePreviewButton = document.createElement("a");
|
||||
additionalNode.appendChild(replacePreviewButton);
|
||||
if (replacePreviewButton === undefined) {
|
||||
replacePreviewButton = document.createElement('a');
|
||||
additionalNode.append(replacePreviewButton);
|
||||
}
|
||||
|
||||
// Check thumb mode
|
||||
|
||||
@ -7,7 +7,11 @@ export default (token: Theme) => {
|
||||
linear-gradient(-45deg, ${token.colorFillTertiary} 25%, transparent 25%),
|
||||
linear-gradient(45deg, transparent 75%, ${token.colorFillTertiary} 75%),
|
||||
linear-gradient(-45deg, transparent 75%, ${token.colorFillTertiary} 75%);
|
||||
background-position: 0 0, 0 10px, 10px -10px, -10px 0;
|
||||
background-position:
|
||||
0 0,
|
||||
0 10px,
|
||||
10px -10px,
|
||||
-10px 0;
|
||||
background-size: 20px 20px;
|
||||
border: 2px solid ${token.colorBorderSecondary} !important;
|
||||
border-radius: ${token.borderRadius}px !important;
|
||||
|
||||
@ -91,8 +91,7 @@ export default (token: Theme) => {
|
||||
--block-label-border-color: ${token.colorBorderSecondary};
|
||||
--block-label-border-width: 1px;
|
||||
--block-label-shadow: ${token.boxShadowTertiary};
|
||||
--block-label-text-color: ${token.colorText}
|
||||
--block-label-margin: 0;
|
||||
--block-label-text-color: ${token.colorText} --block-label-margin: 0;
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: ${token.borderRadius}px;
|
||||
--block-label-right-radius: ${token.borderRadius}px;
|
||||
@ -128,7 +127,7 @@ export default (token: Theme) => {
|
||||
--checkbox-border-color-selected: ${token.colorPrimary};
|
||||
--checkbox-border-radius: ${token.borderRadiusXS}px;
|
||||
--checkbox-border-width: 1px;
|
||||
--checkbox-label-background-fill: ${token.colorFillTertiary};
|
||||
--checkbox-label-background-fill: ${token.colorFillTertiary};
|
||||
--checkbox-label-background-fill-hover: ${token.colorFillSecondary};
|
||||
--checkbox-label-background-fill-selected: ${token.colorFillSecondary};
|
||||
--checkbox-label-border-color: ${token.colorBorderSecondary};
|
||||
@ -189,7 +188,7 @@ export default (token: Theme) => {
|
||||
--button-primary-text-color: ${readableColor(token.colorPrimary)};
|
||||
--button-primary-text-color-hover: ${readableColor(token.colorPrimary)};
|
||||
--button-secondary-background-fill: ${token.colorFillSecondary};
|
||||
--button-secondary-background-fill-hover: ${token.colorFill};;
|
||||
--button-secondary-background-fill-hover: ${token.colorFill};
|
||||
--button-secondary-border-color: ${token.colorBorderSecondary};
|
||||
--button-secondary-border-color-hover: ${token.colorBorder};
|
||||
--button-secondary-text-color: ${token.colorTextSecondary};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user