From 9874c2ea1eac9bc737698bf0654217d3f22ef215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:26:02 +0200 Subject: [PATCH 01/10] fix darkmode colors for popovers --- src/ui/styles.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/styles.css b/src/ui/styles.css index 89ee17e..1c4a8e8 100644 --- a/src/ui/styles.css +++ b/src/ui/styles.css @@ -36,6 +36,7 @@ --figma-color-teal-bg: rgb(53, 196, 176, 0.16); --figma-color-red: rgb(255, 46, 83); --figma-color-red-bg: rgb(255, 46, 83, 0.16); + --figma-color-text-primary: #ffffff; } } From 559498cd3e406793825af8347c5449aecab43d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:27:25 +0200 Subject: [PATCH 02/10] fix placeholder color --- src/ui/views/Settings/StringsEditor.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/views/Settings/StringsEditor.css b/src/ui/views/Settings/StringsEditor.css index dfd2b90..0298666 100644 --- a/src/ui/views/Settings/StringsEditor.css +++ b/src/ui/views/Settings/StringsEditor.css @@ -159,3 +159,8 @@ pointer-events: none; opacity: 0.5; } +@media (prefers-color-scheme: dark) { + .strings-editor .cm-placeholder { + color: var(--figma-color-text-primary) !important; + } +} \ No newline at end of file From e5b256c1fcacf6c9a12aaf4e4766b7967a1d40cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:14:07 +0200 Subject: [PATCH 03/10] fix: add hidden layers option to include children --- src/main/utils/nodeTools.ts | 28 ++++++++++++++++++---- src/main/utils/settingsTools.ts | 2 ++ src/types.ts | 1 + src/ui/views/Push/Push.tsx | 5 ---- src/ui/views/Settings/StringsSection.tsx | 30 ++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/main/utils/nodeTools.ts b/src/main/utils/nodeTools.ts index 8ab4f32..ac567b8 100644 --- a/src/main/utils/nodeTools.ts +++ b/src/main/utils/nodeTools.ts @@ -32,11 +32,31 @@ function shouldIncludeNode( return false; } if ( - (settings.ignoreHiddenLayers || - typeof settings.ignoreHiddenLayers === "undefined") && - !node.visible + settings.ignoreHiddenLayers || + typeof settings.ignoreHiddenLayers === "undefined" ) { - return false; + const isNodeVisible = !node.visible; + if (isNodeVisible && !settings.ignoreHiddenLayersIncludingChildren) { + return false; + } + if (settings.ignoreHiddenLayersIncludingChildren) { + let isParentHidden = false; + let parent = node.parent; + try { + while (parent) { + if (!(parent as SceneNode).visible) { + isParentHidden = true; + break; + } + parent = parent.parent; + } + if (isParentHidden) { + return false; + } + } catch (error) { + console.error("Error checking parent visibility:", error); + } + } } if ( settings.ignoreTextLayers && diff --git a/src/main/utils/settingsTools.ts b/src/main/utils/settingsTools.ts index 42c4102..3e64247 100644 --- a/src/main/utils/settingsTools.ts +++ b/src/main/utils/settingsTools.ts @@ -73,6 +73,7 @@ export const setPluginData = async (data: Partial) => { apiKey, apiUrl, ignoreHiddenLayers, + ignoreHiddenLayersIncludingChildren, ignoreNumbers, ignorePrefix, ignoreTextLayers, @@ -92,6 +93,7 @@ export const setPluginData = async (data: Partial) => { apiUrl, documentInfo: true, ignoreHiddenLayers, + ignoreHiddenLayersIncludingChildren, ignoreNumbers, ignorePrefix, ignoreTextLayers, diff --git a/src/types.ts b/src/types.ts index d607019..3b48f27 100644 --- a/src/types.ts +++ b/src/types.ts @@ -115,6 +115,7 @@ export type GlobalSettings = { */ keyFormat?: string; ignoreHiddenLayers?: boolean; + ignoreHiddenLayersIncludingChildren?: boolean; ignoreTextLayers?: boolean; variableCasing?: | "snake_case" diff --git a/src/ui/views/Push/Push.tsx b/src/ui/views/Push/Push.tsx index 61dca45..7e22fce 100644 --- a/src/ui/views/Push/Push.tsx +++ b/src/ui/views/Push/Push.tsx @@ -112,11 +112,6 @@ export const Push: FunctionalComponent = () => { method: "post", }); - const addNewTranslations = useApiMutation({ - url: "/v2/projects/keys/import", - method: "post", - }); - const addTagsToKeys = useApiMutation({ url: "/v2/projects/tag-complex", method: "put", diff --git a/src/ui/views/Settings/StringsSection.tsx b/src/ui/views/Settings/StringsSection.tsx index 288694e..417ec30 100644 --- a/src/ui/views/Settings/StringsSection.tsx +++ b/src/ui/views/Settings/StringsSection.tsx @@ -118,6 +118,11 @@ export const StringsSection: FunctionComponent = ({ const [ignoreHiddenLayers, setIgnoreHiddenLayers] = useState( tolgeeConfig.ignoreHiddenLayers ?? true ); + const [ + ignoreHiddenLayersIncludingChildren, + setIgnoreHiddenLayersIncludingChildren, + ] = useState(tolgeeConfig.ignoreHiddenLayersIncludingChildren ?? false); + const [ignoreTextLayers, setIgnoreTextLayers] = useState( tolgeeConfig.ignoreTextLayers ?? false ); @@ -177,6 +182,16 @@ export const StringsSection: FunctionComponent = ({ }); } + function handleIgnoreHiddenLayersIncludingChildrenChange( + event: TargetedEvent + ): void { + setIgnoreHiddenLayersIncludingChildren(event.currentTarget.checked); + setTolgeeConfig({ + ...tolgeeConfig, + ignoreHiddenLayersIncludingChildren: event.currentTarget.checked, + }); + } + function handleTextLayersChange( event: TargetedEvent ): void { @@ -282,6 +297,21 @@ export const StringsSection: FunctionComponent = ({ hidden layers + {ignoreHiddenLayers && ( + + +
+ + + including all child texts + + +
+
+ )}
Date: Sat, 18 Oct 2025 16:16:10 +0200 Subject: [PATCH 04/10] add better error message --- src/ui/views/Pull/Pull.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ui/views/Pull/Pull.tsx b/src/ui/views/Pull/Pull.tsx index 5375abc..35990f1 100644 --- a/src/ui/views/Pull/Pull.tsx +++ b/src/ui/views/Pull/Pull.tsx @@ -53,6 +53,10 @@ export const Pull: FunctionalComponent = ({ lang }) => { } catch (e) { if (e === "invalid_project_api_key") { setError("Invalid project API key"); + } else if (e === "too_many_uploaded_images") { + setError( + "Too many uploaded images. Disable update screenshots in settings." + ); } else { setError(`Cannot get translation data. ${e}`); } From 9acf8ea3f2d42886954ad63827d1b3097a168522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:48:30 +0200 Subject: [PATCH 05/10] optimize error handling and text that are displayed --- src/ui/views/Push/Push.tsx | 96 ++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/src/ui/views/Push/Push.tsx b/src/ui/views/Push/Push.tsx index 7e22fce..d113580 100644 --- a/src/ui/views/Push/Push.tsx +++ b/src/ui/views/Push/Push.tsx @@ -44,6 +44,7 @@ export const Push: FunctionalComponent = () => { const [changes, setChanges] = useState(); const selectedNodes = useConnectedNodes({ ignoreSelection: false }); const tolgeeConfig = useGlobalState((c) => c.config); + const [screenshotCount, setScreenshotCount] = useState(0); const nodes = selectedNodes.data?.items ?? []; @@ -226,7 +227,7 @@ export const Push: FunctionalComponent = () => { translations: { [language]: { text: item.newValue, - resolution: "OVERRIDE", + resolution: item.oldValue ? "OVERRIDE" : "NEW", }, }, }); @@ -251,44 +252,63 @@ export const Push: FunctionalComponent = () => { }, }); - // Add tags to keys - if ( - (tolgeeConfig?.addTags ?? false) && - tolgeeConfig?.tags && - tolgeeConfig.tags.length > 0 - ) { - await addTagsToKeys.mutateAsync({ - content: { - "application/json": { - tagFiltered: tolgeeConfig?.tags ?? [], - filterKeys: [ - ...changes.newKeys, - ...changes.unchangedKeys, - ...changes.changedKeys, - ].map((k) => ({ - name: k.key, - namespace: k.ns || undefined, - })), + try { + // Add tags to keys + if ( + (tolgeeConfig?.addTags ?? false) && + tolgeeConfig?.tags && + tolgeeConfig.tags.length > 0 + ) { + await addTagsToKeys.mutateAsync({ + content: { + "application/json": { + tagFiltered: tolgeeConfig?.tags ?? [], + filterKeys: [ + ...changes.newKeys, + ...changes.unchangedKeys, + ...changes.changedKeys, + ].map((k) => ({ + name: k.key, + namespace: k.ns || undefined, + })), + }, }, - }, - }); + }); + } + } catch (e) { + setErrorMessage( + `Error adding tags. ${e}. Translations were still updated.` + ); } if (tolgeeConfig?.updateScreenshots ?? true) { for (const screenshot of changes.screenshots.values()) { - const relatedKeys = screenshot.keys - .map((data) => ({ - keyName: data.key, - namespace: data.ns || undefined, - })) - .slice(0, 100); - await bigMeta.mutateAsync({ - content: { - "application/json": { - relatedKeysInOrder: relatedKeys, + try { + const relatedKeys = screenshot.keys + .map((data) => ({ + keyName: data.key, + namespace: data.ns || undefined, + })) + .slice(0, 100); + await bigMeta.mutateAsync({ + content: { + "application/json": { + relatedKeysInOrder: relatedKeys, + }, }, - }, - }); + }); + setScreenshotCount(screenshotCount + 1); + } catch (e) { + if (e === "too_many_uploaded_images") { + setErrorMessage( + "Too many uploaded images. Disable update screenshots in settings. Translations were still updated." + ); + } else { + setErrorMessage( + `Error updating screenshots. ${e}. Translations were still updated.` + ); + } + } } } @@ -298,8 +318,14 @@ export const Push: FunctionalComponent = () => { setError(true); if (e === "invalid_project_api_key") { setErrorMessage("Invalid project API key"); + } else if (e === "too_many_uploaded_images") { + setErrorMessage( + "Too many uploaded images. Disable update screenshots in settings." + ); + } else if (e === "import_keys_error") { + setErrorMessage("Error importing keys. Please try again."); } else { - setErrorMessage(`Cannot get translation data. ${e}`); + setErrorMessage(`Cannot push translations. ${e}`); } console.error(e); } finally { @@ -322,8 +348,6 @@ export const Push: FunctionalComponent = () => { ? changes.changedKeys.length + changes.newKeys.length : 0; - const screenshotCount = changes?.screenshots.length || 0; - const noChanges = changesSize === 0; return ( From 4c9e4351f600e82940e66f1d7dd9e30704c31af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Tue, 21 Oct 2025 13:20:59 +0200 Subject: [PATCH 06/10] fix screenshot label issue --- src/ui/views/Push/Push.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ui/views/Push/Push.tsx b/src/ui/views/Push/Push.tsx index d113580..43b701b 100644 --- a/src/ui/views/Push/Push.tsx +++ b/src/ui/views/Push/Push.tsx @@ -101,6 +101,10 @@ export const Push: FunctionalComponent = () => { computeDiff(); }, [nodes.length]); + const totalScreenshotCount = useMemo(() => { + return changes?.screenshots.length || 0; + }, [changes]); + const setNodesDataMutation = useSetNodesDataMutation(); const loadingStatus = @@ -392,7 +396,7 @@ export const Push: FunctionalComponent = () => { ) : ( - {screenshotCount !== 0 && ( + {totalScreenshotCount !== 0 && ( { setUploadScreenshots(Boolean(e.currentTarget.checked)) } > - Upload {screenshotCount} screenshot(s) + Upload {totalScreenshotCount} screenshot(s) @@ -416,7 +420,8 @@ export const Push: FunctionalComponent = () => { > Cancel - {noChanges && (screenshotCount === 0 || !uploadScreenshots) ? ( + {noChanges && + (totalScreenshotCount === 0 || !uploadScreenshots) ? (
From 66cc799a95183b1fbc080fe8ad493db6b4a385b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Mon, 27 Oct 2025 16:16:29 +0100 Subject: [PATCH 08/10] add hidden layers tooltip --- .../ActionsBottom/ActionsBottom.css | 2 +- src/ui/components/InfoTooltip/InfoTooltip.css | 1 + src/ui/views/Settings/StringsSection.tsx | 47 ++++++++++++------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/ui/components/ActionsBottom/ActionsBottom.css b/src/ui/components/ActionsBottom/ActionsBottom.css index c5e0f2e..21e477c 100644 --- a/src/ui/components/ActionsBottom/ActionsBottom.css +++ b/src/ui/components/ActionsBottom/ActionsBottom.css @@ -7,7 +7,7 @@ flex-direction: column; align-items: flex-end; background-color: var(--figma-color-bg); - z-index: 1; + z-index: 2; } .actions { diff --git a/src/ui/components/InfoTooltip/InfoTooltip.css b/src/ui/components/InfoTooltip/InfoTooltip.css index 28f8aa2..fed355b 100644 --- a/src/ui/components/InfoTooltip/InfoTooltip.css +++ b/src/ui/components/InfoTooltip/InfoTooltip.css @@ -3,5 +3,6 @@ align-items: center; justify-content: center; cursor: pointer; + z-index: 2; color: var(--figma-color-text-primary); } diff --git a/src/ui/views/Settings/StringsSection.tsx b/src/ui/views/Settings/StringsSection.tsx index 417ec30..d3d2448 100644 --- a/src/ui/views/Settings/StringsSection.tsx +++ b/src/ui/views/Settings/StringsSection.tsx @@ -79,6 +79,24 @@ const keyFormatHelpText = ( ); +const hiddenLayersHelpText = ( + +
+ Skips layers with visibility turned off in Figma. +
+
+ With "Including all child texts" enabled, +
+ all text layers inside hidden layers are +
+ also ignored, even if individually set to visible. +
+
+ Otherwise, only the hidden layer itself is ignored. +
+
+); + const formattingStyleHelpText = (
@@ -284,19 +302,18 @@ export const StringsSection: FunctionComponent = ({ Ignore strings - - numbers - + numbers - - - hidden layers - - + + + hidden layers + + {hiddenLayersHelpText} + {ignoreHiddenLayers && ( @@ -305,9 +322,7 @@ export const StringsSection: FunctionComponent = ({ value={ignoreHiddenLayersIncludingChildren} onChange={handleIgnoreHiddenLayersIncludingChildrenChange} > - - including all child texts - + including all child texts
@@ -319,9 +334,7 @@ export const StringsSection: FunctionComponent = ({ value={ignoreTextLayers} onChange={handleTextLayersChange} > - - text layers with prefix - + text layers with prefix Date: Mon, 27 Oct 2025 16:21:54 +0100 Subject: [PATCH 09/10] fix issue with hidden layers false negatives --- src/main/utils/nodeTools.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/utils/nodeTools.ts b/src/main/utils/nodeTools.ts index ac567b8..55122c9 100644 --- a/src/main/utils/nodeTools.ts +++ b/src/main/utils/nodeTools.ts @@ -32,11 +32,12 @@ function shouldIncludeNode( return false; } if ( - settings.ignoreHiddenLayers || - typeof settings.ignoreHiddenLayers === "undefined" + !node.visible && + (settings.ignoreHiddenLayers || + typeof settings.ignoreHiddenLayers === "undefined") ) { - const isNodeVisible = !node.visible; - if (isNodeVisible && !settings.ignoreHiddenLayersIncludingChildren) { + const nodeIsHidden = !node.visible; + if (nodeIsHidden && !settings.ignoreHiddenLayersIncludingChildren) { return false; } if (settings.ignoreHiddenLayersIncludingChildren) { From f95609e34323501bee2663b37d122e3fae2bf468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20H=C3=BClscher?= <25116822+eweren@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:12:40 +0100 Subject: [PATCH 10/10] fix issues with hidden layers --- src/main/utils/nodeTools.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/utils/nodeTools.ts b/src/main/utils/nodeTools.ts index 55122c9..f8775b5 100644 --- a/src/main/utils/nodeTools.ts +++ b/src/main/utils/nodeTools.ts @@ -32,12 +32,10 @@ function shouldIncludeNode( return false; } if ( - !node.visible && - (settings.ignoreHiddenLayers || - typeof settings.ignoreHiddenLayers === "undefined") + settings.ignoreHiddenLayers || + typeof settings.ignoreHiddenLayers === "undefined" ) { - const nodeIsHidden = !node.visible; - if (nodeIsHidden && !settings.ignoreHiddenLayersIncludingChildren) { + if (!node.visible) { return false; } if (settings.ignoreHiddenLayersIncludingChildren) { @@ -45,7 +43,8 @@ function shouldIncludeNode( let parent = node.parent; try { while (parent) { - if (!(parent as SceneNode).visible) { + if ("visible" in parent && !(parent as SceneNode).visible) { + console.log(parent, "PARENT HIDDEN"); isParentHidden = true; break; }