fix: remove TODO tips in locales
This commit is contained in:
@@ -31,6 +31,7 @@ export default function useDrawing(props: {
|
|||||||
const autoScale = useRef<number>(1);
|
const autoScale = useRef<number>(1);
|
||||||
const baseScale = useRef<number>(1);
|
const baseScale = useRef<number>(1);
|
||||||
const contentPos = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
const contentPos = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
||||||
|
const maskStorkeRef = useRef<Stroke[]>([]);
|
||||||
|
|
||||||
const disabled = useMemo(() => {
|
const disabled = useMemo(() => {
|
||||||
return isDisabled || invertMask || !!maskUpload?.length;
|
return isDisabled || invertMask || !!maskUpload?.length;
|
||||||
@@ -40,6 +41,10 @@ export default function useDrawing(props: {
|
|||||||
strokesRef.current = strokes;
|
strokesRef.current = strokes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setMaskStrokes = (strokes: Stroke[]) => {
|
||||||
|
maskStorkeRef.current = strokes;
|
||||||
|
};
|
||||||
|
|
||||||
const inpaintArea = useCallback(
|
const inpaintArea = useCallback(
|
||||||
(data: Uint8ClampedArray<ArrayBufferLike>) => {
|
(data: Uint8ClampedArray<ArrayBufferLike>) => {
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
@@ -61,7 +66,7 @@ export default function useDrawing(props: {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const generateMask = useCallback(() => {
|
const generateMask = useCallback(() => {
|
||||||
if (strokesRef.current.length === 0) {
|
if (strokesRef.current.length === 0 && maskStorkeRef.current.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const overlayCanvas = overlayCanvasRef.current!;
|
const overlayCanvas = overlayCanvasRef.current!;
|
||||||
@@ -180,7 +185,6 @@ export default function useDrawing(props: {
|
|||||||
|
|
||||||
stroke.forEach((point, i) => {
|
stroke.forEach((point, i) => {
|
||||||
const { x, y } = getTransformedPoint(point.x, point.y);
|
const { x, y } = getTransformedPoint(point.x, point.y);
|
||||||
console.log('Drawing point:');
|
|
||||||
ctx.lineWidth = getTransformLineWidth(point.lineWidth);
|
ctx.lineWidth = getTransformLineWidth(point.lineWidth);
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
ctx.moveTo(x, y);
|
ctx.moveTo(x, y);
|
||||||
@@ -374,6 +378,8 @@ export default function useDrawing(props: {
|
|||||||
mouseDownState,
|
mouseDownState,
|
||||||
autoScale,
|
autoScale,
|
||||||
baseScale,
|
baseScale,
|
||||||
|
maskStorkeRef,
|
||||||
|
setMaskStrokes,
|
||||||
fitView,
|
fitView,
|
||||||
setStrokes,
|
setStrokes,
|
||||||
resetCanvas,
|
resetCanvas,
|
||||||
|
|||||||
@@ -21,6 +21,10 @@
|
|||||||
cursor: none !important;
|
cursor: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlay-canvas.overlay-canvas--disabled:hover {
|
||||||
|
cursor: default !important;
|
||||||
|
}
|
||||||
|
|
||||||
.upload-mask {
|
.upload-mask {
|
||||||
&:hover {
|
&:hover {
|
||||||
.close-btn {
|
.close-btn {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import React, {
|
import React, {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
@@ -56,6 +57,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
const translatePos = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
const translatePos = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
||||||
const negativeMaskRef = useRef<boolean>(false);
|
const negativeMaskRef = useRef<boolean>(false);
|
||||||
const [invertMask, setInvertMask] = useState<boolean>(false);
|
const [invertMask, setInvertMask] = useState<boolean>(false);
|
||||||
|
const timer = useRef<any>(null);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
canvasRef,
|
canvasRef,
|
||||||
@@ -66,6 +68,8 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
mouseDownState,
|
mouseDownState,
|
||||||
autoScale,
|
autoScale,
|
||||||
baseScale,
|
baseScale,
|
||||||
|
maskStorkeRef,
|
||||||
|
setMaskStrokes,
|
||||||
draw,
|
draw,
|
||||||
drawStroke,
|
drawStroke,
|
||||||
startDrawing,
|
startDrawing,
|
||||||
@@ -131,20 +135,25 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
options: {
|
options: {
|
||||||
lineWidth?: number;
|
lineWidth?: number;
|
||||||
color: string;
|
color: string;
|
||||||
compositeOperation: 'source-over' | 'destination-out';
|
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
const { color, compositeOperation } = options;
|
const { color } = options;
|
||||||
|
|
||||||
ctx.globalCompositeOperation = compositeOperation;
|
|
||||||
|
|
||||||
stroke.forEach((point) => {
|
stroke.forEach((point) => {
|
||||||
const { x, y } = getTransformedPoint(point.x, point.y);
|
const { x, y } = getTransformedPoint(point.x, point.y);
|
||||||
ctx.save();
|
|
||||||
const width = getTransformLineWidth(point.lineWidth);
|
const width = getTransformLineWidth(point.lineWidth);
|
||||||
ctx.fillStyle = color;
|
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
|
||||||
|
// erase the previous stroke
|
||||||
|
ctx.globalCompositeOperation = 'destination-out';
|
||||||
ctx.fillRect(x - width / 2, y - width / 2, width, width);
|
ctx.fillRect(x - width / 2, y - width / 2, width, width);
|
||||||
|
|
||||||
|
// draw the new stroke
|
||||||
|
ctx.globalCompositeOperation = 'source-over';
|
||||||
|
ctx.fillStyle = color;
|
||||||
|
ctx.fillRect(x - width / 2, y - width / 2, width, width);
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -159,76 +168,81 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
console.log('Resetting strokes', currentStroke.current);
|
console.log('Resetting strokes', currentStroke.current);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const redrawStrokes = useCallback(
|
const loadMaskPixs = (strokes: Stroke[]) => {
|
||||||
(strokes: Stroke[], type?: string) => {
|
clearOverlayCanvas();
|
||||||
console.log('Redrawing strokes:', strokes, type);
|
if (!strokes.length) {
|
||||||
clearOverlayCanvas();
|
return;
|
||||||
if (!strokes.length) {
|
}
|
||||||
return;
|
console.log('loadin mask pixs:');
|
||||||
}
|
const overlayCanvas = overlayCanvasRef.current!;
|
||||||
|
const overlayCtx = overlayCanvas!.getContext('2d')!;
|
||||||
|
|
||||||
const overlayCanvas = overlayCanvasRef.current!;
|
setTransform();
|
||||||
|
|
||||||
const overlayCtx = overlayCanvas!.getContext('2d')!;
|
strokes?.forEach((stroke: Point[], index) => {
|
||||||
|
drawFillRect(overlayCtx, stroke, {
|
||||||
// clear offscreen canvas
|
color: COLOR
|
||||||
|
|
||||||
setTransform();
|
|
||||||
|
|
||||||
strokes?.forEach((stroke: Point[], index) => {
|
|
||||||
overlayCtx.save();
|
|
||||||
drawStroke(overlayCtx, stroke, {
|
|
||||||
color: COLOR,
|
|
||||||
compositeOperation: 'destination-out'
|
|
||||||
});
|
|
||||||
|
|
||||||
drawStroke(overlayCtx, stroke, {
|
|
||||||
color: COLOR,
|
|
||||||
compositeOperation: 'source-over'
|
|
||||||
});
|
|
||||||
overlayCtx.restore();
|
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
[drawStroke]
|
};
|
||||||
);
|
const redrawStrokes = (strokes: Stroke[], type?: string) => {
|
||||||
|
console.log('Redrawing strokes:', strokes, type);
|
||||||
|
clearOverlayCanvas();
|
||||||
|
if (!strokes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const loadMaskPixs = useCallback(
|
const overlayCanvas = overlayCanvasRef.current!;
|
||||||
(strokes: Stroke[], type?: string) => {
|
|
||||||
clearOverlayCanvas();
|
|
||||||
if (!strokes.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log('loadin mask pixs:');
|
|
||||||
const overlayCanvas = overlayCanvasRef.current!;
|
|
||||||
const overlayCtx = overlayCanvas!.getContext('2d')!;
|
|
||||||
|
|
||||||
setTransform();
|
const overlayCtx = overlayCanvas!.getContext('2d')!;
|
||||||
|
|
||||||
strokes?.forEach((stroke: Point[], index) => {
|
// clear offscreen canvas
|
||||||
overlayCtx.save();
|
|
||||||
drawFillRect(overlayCtx, stroke, {
|
|
||||||
color: COLOR,
|
|
||||||
compositeOperation: 'destination-out'
|
|
||||||
});
|
|
||||||
|
|
||||||
drawFillRect(overlayCtx, stroke, {
|
setTransform();
|
||||||
color: COLOR,
|
overlayCtx.save();
|
||||||
compositeOperation: 'source-over'
|
loadMaskPixs(maskStorkeRef.current);
|
||||||
});
|
|
||||||
overlayCtx.restore();
|
strokes?.forEach((stroke: Point[], index) => {
|
||||||
|
drawStroke(overlayCtx, stroke, {
|
||||||
|
color: COLOR,
|
||||||
|
compositeOperation: 'destination-out'
|
||||||
});
|
});
|
||||||
},
|
|
||||||
[drawFillRect]
|
drawStroke(overlayCtx, stroke, {
|
||||||
);
|
color: COLOR,
|
||||||
|
compositeOperation: 'source-over'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
overlayCtx.restore();
|
||||||
|
};
|
||||||
|
|
||||||
const undo = () => {
|
const undo = () => {
|
||||||
if (strokesRef.current.length === 0) return;
|
if (
|
||||||
|
strokesRef.current.length === 0 &&
|
||||||
|
maskStorkeRef.current.length === 0
|
||||||
|
) {
|
||||||
|
clearOverlayCanvas();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const newStrokes = strokesRef.current.slice(0, -1);
|
const newStrokes = strokesRef.current.slice(0, -1);
|
||||||
console.log('New strokes:', newStrokes, strokesRef.current);
|
|
||||||
setStrokes(newStrokes);
|
setStrokes(newStrokes);
|
||||||
|
|
||||||
redrawStrokes(newStrokes);
|
console.log(
|
||||||
|
'newstrokes=======',
|
||||||
|
newStrokes.length,
|
||||||
|
maskStorkeRef.current.length
|
||||||
|
);
|
||||||
|
|
||||||
|
if (strokesRef.current.length) {
|
||||||
|
clearTimeout(timer.current);
|
||||||
|
timer.current = setTimeout(() => {
|
||||||
|
redrawStrokes(strokesRef.current);
|
||||||
|
}, 100);
|
||||||
|
} else if (maskStorkeRef.current.length) {
|
||||||
|
loadMaskPixs(maskStorkeRef.current);
|
||||||
|
setMaskStrokes([]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadOriginImage = () => {
|
const downloadOriginImage = () => {
|
||||||
@@ -424,6 +438,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
// mouse up
|
// mouse up
|
||||||
window.addEventListener('mouseup', handleMouseUp);
|
window.addEventListener('mouseup', handleMouseUp);
|
||||||
return () => {
|
return () => {
|
||||||
|
clearTimeout(timer.current);
|
||||||
window.removeEventListener('keydown', handleUndoShortcut);
|
window.removeEventListener('keydown', handleUndoShortcut);
|
||||||
window.removeEventListener('mousedown', handleMouseDown);
|
window.removeEventListener('mousedown', handleMouseDown);
|
||||||
window.removeEventListener('mouseup', handleMouseUp);
|
window.removeEventListener('mouseup', handleMouseUp);
|
||||||
@@ -439,7 +454,8 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
clearMask: handleDeleteMask,
|
clearMask: handleDeleteMask,
|
||||||
loadMaskPixs(strokes: Stroke[]) {
|
loadMaskPixs(strokes: Stroke[]) {
|
||||||
setStrokes(strokes);
|
setMaskStrokes(strokes);
|
||||||
|
setStrokes([]);
|
||||||
loadMaskPixs(strokes);
|
loadMaskPixs(strokes);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -494,7 +510,9 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
<canvas ref={canvasRef} style={{ position: 'absolute', zIndex: 1 }} />
|
<canvas ref={canvasRef} style={{ position: 'absolute', zIndex: 1 }} />
|
||||||
<canvas
|
<canvas
|
||||||
ref={overlayCanvasRef}
|
ref={overlayCanvasRef}
|
||||||
className="overlay-canvas"
|
className={classNames('overlay-canvas', {
|
||||||
|
'overlay-canvas--disabled': disabled
|
||||||
|
})}
|
||||||
style={{ position: 'absolute', zIndex: 10, cursor: 'none' }}
|
style={{ position: 'absolute', zIndex: 10, cursor: 'none' }}
|
||||||
onMouseDown={(event) => {
|
onMouseDown={(event) => {
|
||||||
mouseDownState.current = true;
|
mouseDownState.current = true;
|
||||||
|
|||||||
+4
-14
@@ -24,24 +24,14 @@ To add a new language configuration, follow these steps:
|
|||||||
|
|
||||||
- Open the `.ts` file in the **new directory**.
|
- Open the `.ts` file in the **new directory**.
|
||||||
- For each key-value pair:
|
- For each key-value pair:
|
||||||
|
|
||||||
- If a translation is available, replace the value with the translated text.
|
- If a translation is available, replace the value with the translated text.
|
||||||
- If no translation is available yet, **replace the value with** `TODO: Translate key "<original-key>"`.
|
- If no translation is available, keep the `English` value as default.
|
||||||
- This ensures that the key is visible for contributors to know exactly what needs to be translated.
|
|
||||||
|
|
||||||
**Example:**
|
- **Note**: Keeping the English text as the default ensures the application remains functional even if some translations are missing.
|
||||||
|
|
||||||
```ts
|
|
||||||
export default {
|
|
||||||
'playground.image.mask.upload':
|
|
||||||
'TODO: Translate key "playground.image.mask.upload"',
|
|
||||||
'welcome.message': 'TODO: Translate key "welcome.message"'
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Important**: The `TODO` message should include the original key in quotes so that contributors can easily identify which key needs translation without needing to look at the code itself.
|
|
||||||
|
|
||||||
## 4. **Finalize the Configuration**
|
## 4. **Finalize the Configuration**
|
||||||
|
|
||||||
- Review and ensure all translations are complete.
|
- Review and ensure all translations are complete.
|
||||||
- If any translations are missing, contributors can later replace `"TODO: Translate key '...'` with the correct translation.
|
- If any translations are missing, they will default to `English`.
|
||||||
- Your new language configuration is now ready for use!
|
- Your new language configuration is now ready for use!
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export default {
|
|||||||
'models.form.filePath': 'Путь к модели',
|
'models.form.filePath': 'Путь к модели',
|
||||||
'models.form.backendVersion': 'Версия бэкенда',
|
'models.form.backendVersion': 'Версия бэкенда',
|
||||||
'models.form.backendVersion.tips':
|
'models.form.backendVersion.tips':
|
||||||
'TODO: Translate key "models.form.backendVersion.tips"',
|
'To use the desired version of vLLM/llama-box/vox-box, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}',
|
||||||
'models.form.gpuselector': 'Селектор GPU',
|
'models.form.gpuselector': 'Селектор GPU',
|
||||||
'models.form.backend.llamabox':
|
'models.form.backend.llamabox':
|
||||||
'Для моделей формата GGUF. Поддержка Linux, macOS и Windows.',
|
'Для моделей формата GGUF. Поддержка Linux, macOS и Windows.',
|
||||||
@@ -110,10 +110,17 @@ export default {
|
|||||||
'models.table.vllmAcrossworker': 'vLLM между воркерами',
|
'models.table.vllmAcrossworker': 'vLLM между воркерами',
|
||||||
'models.form.releases': 'Релизы',
|
'models.form.releases': 'Релизы',
|
||||||
'models.form.moreparameters': 'Описание параметров',
|
'models.form.moreparameters': 'Описание параметров',
|
||||||
'models.table.vram.allocated':
|
'models.table.vram.allocated': 'Allocated VRAM',
|
||||||
'TODO: Translate key "models.table.vram.allocated"',
|
|
||||||
'models.form.backend.warning':
|
'models.form.backend.warning':
|
||||||
'TODO: Translate key "models.form.backend.warning"',
|
'The backend for GGUF format models uses llama-box.',
|
||||||
'models.form.backend.warning.llamabox':
|
'models.form.backend.warning.llamabox': `To use the llama-box backend, specify the full path to the model file (e.g.,<span style="font-weight: 700">/data/models/model.gguf</span>). For sharded models, provide the path to the first shard (e.g.,<span style="font-weight: 700">/data/models/model-00001-of-00004.gguf</span>).`
|
||||||
"TODO: Translate key 'models.form.backend.warning.llamabox'"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
|
||||||
|
// 1. models.form.backendVersion.tips
|
||||||
|
// 2. models.form.backend.warning
|
||||||
|
// 3. models.form.backend.warning.llamabox
|
||||||
|
// 4. models.table.vram.allocated
|
||||||
|
|
||||||
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -137,14 +137,22 @@ export default {
|
|||||||
'playground.image.edit': 'Редактировать',
|
'playground.image.edit': 'Редактировать',
|
||||||
'playground.image.fitview': 'Подогнать размер',
|
'playground.image.fitview': 'Подогнать размер',
|
||||||
'playground.chat.aithought': 'Рассуждение (CoT)',
|
'playground.chat.aithought': 'Рассуждение (CoT)',
|
||||||
'playground.chat.thinking': 'TODO: Translate key "playground.chat.thinking"',
|
'playground.chat.thinking': 'Thinking...',
|
||||||
'playground.image.mask.uploaded': 'Маска загружена',
|
'playground.image.mask.uploaded': 'Маска загружена',
|
||||||
'playground.image.mask.upload':
|
'playground.image.mask.upload':
|
||||||
'TODO: Translate key "playground.image.mask.upload"',
|
'Upload Mask: No additional drawing allowed after upload.',
|
||||||
'playground.params.frequency_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения токенов, уже часто встречающихся в тексте, уменьшая склонность модели дословно повторять одни и те же фразы.`,
|
'playground.params.frequency_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения токенов, уже часто встречающихся в тексте, уменьшая склонность модели дословно повторять одни и те же фразы.`,
|
||||||
'playground.params.presence_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения любых токенов, присутствующих в тексте, повышая склонность модели к обсуждению новых тем.`,
|
'playground.params.presence_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения любых токенов, присутствующих в тексте, повышая склонность модели к обсуждению новых тем.`,
|
||||||
'playground.image.origin': 'Оригинал',
|
'playground.image.origin': 'Оригинал',
|
||||||
'playground.image.mask': 'Маска',
|
'playground.image.mask': 'Маска',
|
||||||
'playground.image.negativeMask.tips':
|
'playground.image.negativeMask.tips':
|
||||||
'TODO: Translate key "playground.image.negativeMask.tips"'
|
'1. After selection, no further masking can be drawn; therefore, you should draw the mask first and then check the option.\n 2. Once a mask image is uploaded, no further masks can be generated.'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
|
||||||
|
// 1. playground.chat.thinking
|
||||||
|
// 2. playground.image.mask.upload
|
||||||
|
// 3. playground.image.negativeMask.tips
|
||||||
|
|
||||||
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -183,6 +183,14 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
return <GPUCard data={data}></GPUCard>;
|
return <GPUCard data={data}></GPUCard>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tagRender = (props: any) => {
|
||||||
|
if (props.isMaxTag) {
|
||||||
|
return props.label;
|
||||||
|
}
|
||||||
|
const parent = _.split(props.value, '__RC_CASCADER_SPLIT__')?.[0];
|
||||||
|
return `${parent} / ${props?.label}`;
|
||||||
|
};
|
||||||
|
|
||||||
const collapseItems = useMemo(() => {
|
const collapseItems = useMemo(() => {
|
||||||
const children = (
|
const children = (
|
||||||
<>
|
<>
|
||||||
@@ -313,7 +321,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
onClose={props.onClose}
|
onClose={props.onClose}
|
||||||
maxWidth={240}
|
maxWidth={240}
|
||||||
>
|
>
|
||||||
{props.label}
|
{tagRender(props)}
|
||||||
</AutoTooltip>
|
</AutoTooltip>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user