Compare commits

..

1 Commits

Author SHA1 Message Date
hikari 10e013a983 feat: add image input to art/avatar modes and notes to replace mode
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m15s
CI / Lint & Check (pull_request) Successful in 12m57s
CI / Build Windows (pull_request) Failing after 21m39s
- Art and Avatar modes now support optional image uploads via paste or
  file picker, sent to Gemini alongside the text prompt
- Initial Replace mode gains an optional textarea for notes to include
  with the uploaded image
- Backend updated to send user images for all modes, appending replace
  instructions only when in replace mode
- Send validation updated to allow image-only messages in art/avatar
2026-04-13 09:18:20 -07:00
4 changed files with 134 additions and 118 deletions
+1 -1
View File
@@ -27,7 +27,7 @@
"eslint": "9.25.1",
"postcss": "8.5.3",
"tailwindcss": "3.4.17",
"typescript": "6.0.2",
"typescript": "5.8.3",
"vite": "6.3.2",
"@vitejs/plugin-react": "4.4.1"
}
+73 -73
View File
@@ -26,10 +26,10 @@ importers:
devDependencies:
'@nhcarrigan/eslint-config':
specifier: 5.2.0
version: 5.2.0(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))(playwright@1.59.1)(react@19.1.0)(typescript@6.0.2)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))
version: 5.2.0(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))(playwright@1.59.1)(react@19.1.0)(typescript@5.8.3)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))
'@nhcarrigan/typescript-config':
specifier: 4.0.0
version: 4.0.0(typescript@6.0.2)
version: 4.0.0(typescript@5.8.3)
'@tauri-apps/cli':
specifier: 2.5.0
version: 2.5.0
@@ -55,8 +55,8 @@ importers:
specifier: 3.4.17
version: 3.4.17
typescript:
specifier: 6.0.2
version: 6.0.2
specifier: 5.8.3
version: 5.8.3
vite:
specifier: 6.3.2
version: 6.3.2(jiti@1.21.7)(yaml@2.8.3)
@@ -2260,8 +2260,8 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
typescript@6.0.2:
resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==}
typescript@5.8.3:
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
engines: {node: '>=14.17'}
hasBin: true
@@ -2707,19 +2707,19 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@nhcarrigan/eslint-config@5.2.0(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))(playwright@1.59.1)(react@19.1.0)(typescript@6.0.2)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))':
'@nhcarrigan/eslint-config@5.2.0(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))(playwright@1.59.1)(react@19.1.0)(typescript@5.8.3)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))':
dependencies:
'@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.25.1(jiti@1.21.7))
'@eslint/compat': 1.2.4(eslint@9.25.1(jiti@1.21.7))
'@eslint/eslintrc': 3.2.0
'@eslint/js': 9.17.0
'@stylistic/eslint-plugin': 2.12.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/eslint-plugin': 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@vitest/eslint-plugin': 1.1.24(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))
'@stylistic/eslint-plugin': 2.12.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
'@typescript-eslint/eslint-plugin': 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
'@vitest/eslint-plugin': 1.1.24(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))
eslint: 9.25.1(jiti@1.21.7)
eslint-plugin-deprecation: 3.0.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))
eslint-plugin-deprecation: 3.0.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))
eslint-plugin-jsdoc: 50.6.1(eslint@9.25.1(jiti@1.21.7))
eslint-plugin-playwright: 2.1.0(eslint@9.25.1(jiti@1.21.7))
eslint-plugin-react: 7.37.3(eslint@9.25.1(jiti@1.21.7))
@@ -2728,7 +2728,7 @@ snapshots:
globals: 15.14.0
playwright: 1.59.1
react: 19.1.0
typescript: 6.0.2
typescript: 5.8.3
vitest: 4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3))
transitivePeerDependencies:
- '@typescript-eslint/utils'
@@ -2736,9 +2736,9 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
'@nhcarrigan/typescript-config@4.0.0(typescript@6.0.2)':
'@nhcarrigan/typescript-config@4.0.0(typescript@5.8.3)':
dependencies:
typescript: 6.0.2
typescript: 5.8.3
'@nodelib/fs.scandir@2.1.5':
dependencies:
@@ -2833,9 +2833,9 @@ snapshots:
'@standard-schema/spec@1.1.0': {}
'@stylistic/eslint-plugin@2.12.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@stylistic/eslint-plugin@2.12.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/utils': 8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/utils': 8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
eslint-visitor-keys: 4.2.1
espree: 10.4.0
@@ -2948,41 +2948,41 @@ snapshots:
dependencies:
csstype: 3.2.3
'@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
'@typescript-eslint/scope-manager': 8.19.0
'@typescript-eslint/type-utils': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/utils': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/type-utils': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
'@typescript-eslint/utils': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.19.0
eslint: 9.25.1(jiti@1.21.7)
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
ts-api-utils: 1.4.3(typescript@6.0.2)
typescript: 6.0.2
ts-api-utils: 1.4.3(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.19.0
'@typescript-eslint/types': 8.19.0
'@typescript-eslint/typescript-estree': 8.19.0(typescript@6.0.2)
'@typescript-eslint/typescript-estree': 8.19.0(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.19.0
debug: 4.4.3
eslint: 9.25.1(jiti@1.21.7)
typescript: 6.0.2
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.58.1(typescript@6.0.2)':
'@typescript-eslint/project-service@8.58.1(typescript@5.8.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.58.1(typescript@6.0.2)
'@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.8.3)
'@typescript-eslint/types': 8.58.1
debug: 4.4.3
typescript: 6.0.2
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
@@ -3001,18 +3001,18 @@ snapshots:
'@typescript-eslint/types': 8.58.1
'@typescript-eslint/visitor-keys': 8.58.1
'@typescript-eslint/tsconfig-utils@8.58.1(typescript@6.0.2)':
'@typescript-eslint/tsconfig-utils@8.58.1(typescript@5.8.3)':
dependencies:
typescript: 6.0.2
typescript: 5.8.3
'@typescript-eslint/type-utils@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@typescript-eslint/type-utils@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.19.0(typescript@6.0.2)
'@typescript-eslint/utils': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/typescript-estree': 8.19.0(typescript@5.8.3)
'@typescript-eslint/utils': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
debug: 4.4.3
eslint: 9.25.1(jiti@1.21.7)
ts-api-utils: 1.4.3(typescript@6.0.2)
typescript: 6.0.2
ts-api-utils: 1.4.3(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
@@ -3022,7 +3022,7 @@ snapshots:
'@typescript-eslint/types@8.58.1': {}
'@typescript-eslint/typescript-estree@7.18.0(typescript@6.0.2)':
'@typescript-eslint/typescript-estree@7.18.0(typescript@5.8.3)':
dependencies:
'@typescript-eslint/types': 7.18.0
'@typescript-eslint/visitor-keys': 7.18.0
@@ -3031,13 +3031,13 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.9
semver: 7.7.4
ts-api-utils: 1.4.3(typescript@6.0.2)
ts-api-utils: 1.4.3(typescript@5.8.3)
optionalDependencies:
typescript: 6.0.2
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.19.0(typescript@6.0.2)':
'@typescript-eslint/typescript-estree@8.19.0(typescript@5.8.3)':
dependencies:
'@typescript-eslint/types': 8.19.0
'@typescript-eslint/visitor-keys': 8.19.0
@@ -3046,56 +3046,56 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.9
semver: 7.7.4
ts-api-utils: 1.4.3(typescript@6.0.2)
typescript: 6.0.2
ts-api-utils: 1.4.3(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.58.1(typescript@6.0.2)':
'@typescript-eslint/typescript-estree@8.58.1(typescript@5.8.3)':
dependencies:
'@typescript-eslint/project-service': 8.58.1(typescript@6.0.2)
'@typescript-eslint/tsconfig-utils': 8.58.1(typescript@6.0.2)
'@typescript-eslint/project-service': 8.58.1(typescript@5.8.3)
'@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.8.3)
'@typescript-eslint/types': 8.58.1
'@typescript-eslint/visitor-keys': 8.58.1
debug: 4.4.3
minimatch: 10.2.5
semver: 7.7.4
tinyglobby: 0.2.16
ts-api-utils: 2.5.0(typescript@6.0.2)
typescript: 6.0.2
ts-api-utils: 2.5.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@7.18.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@typescript-eslint/utils@7.18.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.25.1(jiti@1.21.7))
'@typescript-eslint/scope-manager': 7.18.0
'@typescript-eslint/types': 7.18.0
'@typescript-eslint/typescript-estree': 7.18.0(typescript@6.0.2)
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
transitivePeerDependencies:
- supports-color
- typescript
'@typescript-eslint/utils@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@typescript-eslint/utils@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.25.1(jiti@1.21.7))
'@typescript-eslint/scope-manager': 8.19.0
'@typescript-eslint/types': 8.19.0
'@typescript-eslint/typescript-estree': 8.19.0(typescript@6.0.2)
'@typescript-eslint/typescript-estree': 8.19.0(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
typescript: 6.0.2
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)':
'@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.25.1(jiti@1.21.7))
'@typescript-eslint/scope-manager': 8.58.1
'@typescript-eslint/types': 8.58.1
'@typescript-eslint/typescript-estree': 8.58.1(typescript@6.0.2)
'@typescript-eslint/typescript-estree': 8.58.1(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
typescript: 6.0.2
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
@@ -3125,12 +3125,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@vitest/eslint-plugin@1.1.24(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))':
'@vitest/eslint-plugin@1.1.24(@typescript-eslint/utils@8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)(vitest@4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3)))':
dependencies:
'@typescript-eslint/utils': 8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/utils': 8.58.1(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
optionalDependencies:
typescript: 6.0.2
typescript: 5.8.3
vitest: 4.1.4(vite@6.3.2(jiti@1.21.7)(yaml@2.8.3))
'@vitest/expect@4.1.4':
@@ -3621,27 +3621,27 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint-import-resolver-node@0.3.10)(eslint@9.25.1(jiti@1.21.7)):
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.10)(eslint@9.25.1(jiti@1.21.7)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
eslint-import-resolver-node: 0.3.10
transitivePeerDependencies:
- supports-color
eslint-plugin-deprecation@3.0.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2):
eslint-plugin-deprecation@3.0.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3):
dependencies:
'@typescript-eslint/utils': 7.18.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/utils': 7.18.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
eslint: 9.25.1(jiti@1.21.7)
ts-api-utils: 1.4.3(typescript@6.0.2)
ts-api-utils: 1.4.3(typescript@5.8.3)
tslib: 2.8.1
typescript: 6.0.2
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint@9.25.1(jiti@1.21.7)):
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.25.1(jiti@1.21.7)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -3652,7 +3652,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.25.1(jiti@1.21.7)
eslint-import-resolver-node: 0.3.10
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2))(eslint-import-resolver-node@0.3.10)(eslint@9.25.1(jiti@1.21.7))
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.10)(eslint@9.25.1(jiti@1.21.7))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -3664,7 +3664,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@6.0.2)
'@typescript-eslint/parser': 8.19.0(eslint@9.25.1(jiti@1.21.7))(typescript@5.8.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -4791,13 +4791,13 @@ snapshots:
dependencies:
is-number: 7.0.0
ts-api-utils@1.4.3(typescript@6.0.2):
ts-api-utils@1.4.3(typescript@5.8.3):
dependencies:
typescript: 6.0.2
typescript: 5.8.3
ts-api-utils@2.5.0(typescript@6.0.2):
ts-api-utils@2.5.0(typescript@5.8.3):
dependencies:
typescript: 6.0.2
typescript: 5.8.3
ts-interface-checker@0.1.13: {}
@@ -4853,7 +4853,7 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
typescript@6.0.2: {}
typescript@5.8.3: {}
unbox-primitive@1.1.0:
dependencies:
+14 -10
View File
@@ -83,22 +83,26 @@ fn build_user_gemini_parts(
user_image_base64: &Option<String>,
user_image_mime: &Option<String>,
) -> Vec<Value> {
if mode == "replace" && user_image_base64.is_some() {
if let Some(image_data) = user_image_base64.as_deref() {
let mime = user_image_mime.as_deref().unwrap_or("image/png");
let data = user_image_base64.as_deref().unwrap_or("");
let base_text = user_text.as_deref().unwrap_or("");
let final_text = if base_text.is_empty() {
REPLACE_MODE_APPEND.to_string()
let final_text = if mode == "replace" {
if base_text.is_empty() {
REPLACE_MODE_APPEND.to_string()
} else {
format!("{}\n{}", base_text, REPLACE_MODE_APPEND)
}
} else {
format!("{}\n{}", base_text, REPLACE_MODE_APPEND)
base_text.to_string()
};
vec![
json!({"inlineData": {"mimeType": mime, "data": data}}),
json!({"text": final_text}),
]
let mut parts = vec![json!({"inlineData": {"mimeType": mime, "data": image_data}})];
if !final_text.is_empty() {
parts.push(json!({"text": final_text}));
}
parts
} else {
// Art/avatar mode, or replace mode follow-up correction (text only)
// No image: text-only message
let text = user_text.as_deref().unwrap_or("");
vec![json!({"text": text})]
}
+46 -34
View File
@@ -256,7 +256,8 @@ const inputArea = ({
if (isInitialReplace && imageBase64 === undefined) {
return;
}
if (!isInitialReplace && text.trim().length === 0) {
const hasContent = text.trim().length > 0 || imageBase64 !== undefined;
if (!isInitialReplace && !hasContent) {
return;
}
@@ -332,6 +333,9 @@ const inputArea = ({
: dropZoneInactiveClass,
].join(" ");
const hasNoContent = text.trim().length === 0 && imageBase64 === undefined;
const isSendDisabled = isLoading || hasNoContent;
return (
<div className="border-t border-purple-900/30 p-4 bg-[#0f0a1a]">
<div className="flex items-center gap-2 mb-2">
@@ -397,6 +401,15 @@ const inputArea = ({
type="file"
/>
<textarea
className={textareaClass}
disabled={isLoading}
onChange={handleTextChange}
placeholder="Add notes to include with the image (optional)..."
rows={2}
value={text}
/>
<button
className={replaceButtonClass}
disabled={isLoading || imageBase64 === undefined}
@@ -414,41 +427,40 @@ const inputArea = ({
</div>
: <div className="flex flex-col gap-3">
{mode === "replace"
? <div className="flex flex-col gap-2">
{imagePreview === undefined
? <button
className={pasteButtonClass}
onClick={handlePasteButtonClick}
<div className="flex flex-col gap-2">
{imagePreview === undefined
? <button
className={pasteButtonClass}
onClick={handlePasteButtonClick}
type="button"
>
{mode === "replace"
? "๐Ÿ“‹ Paste replacement image (optional)"
: "๐Ÿ“‹ Paste image (optional)"}
</button>
: <div className="relative inline-block">
<img
alt="Upload preview"
className="max-h-32 rounded-lg border border-purple-700/40"
src={imagePreview}
/>
<button
className={clearButtonClass}
onClick={clearImage}
type="button"
>
{"๐Ÿ“‹ Paste replacement image (optional)"}
{"ร—"}
</button>
: <div className="relative inline-block">
<img
alt="Upload preview"
className="max-h-32 rounded-lg border border-purple-700/40"
src={imagePreview}
/>
<button
className={clearButtonClass}
onClick={clearImage}
type="button"
>
{"ร—"}
</button>
</div>}
<input
accept="image/*"
className="hidden"
onChange={handleFileChange}
ref={fileInputReference}
type="file"
/>
</div>
: null}
</div>}
<input
accept="image/*"
className="hidden"
onChange={handleFileChange}
ref={fileInputReference}
type="file"
/>
</div>
<div className="flex gap-3 items-end">
<textarea
@@ -464,7 +476,7 @@ const inputArea = ({
/>
<button
className={sendButtonClass}
disabled={isLoading || text.trim().length === 0}
disabled={isSendDisabled}
onClick={handleSend}
type="button"
>