feat: multi-photo support in feedback (up to 5 screenshots)
iOS: - PhotosPicker with maxSelectionCount: 5 - Horizontal scroll preview strip with individual remove buttons - Sends "images" array instead of single "image" Server: - Gateway accepts both "image" (single, backwards compat) and "images" (array) fields - Uploads each as separate Gitea issue attachment Also closed Gitea issues #11, #12, #13, #14. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -100,33 +100,40 @@ def handle_feedback(handler, body, user):
|
||||
result = json.loads(resp.read())
|
||||
issue_number = result.get("number")
|
||||
|
||||
# Upload image attachment if provided
|
||||
image_b64 = data.get("image")
|
||||
if image_b64 and issue_number:
|
||||
# Upload image attachments if provided
|
||||
if issue_number:
|
||||
import base64
|
||||
try:
|
||||
img_bytes = base64.b64decode(image_b64)
|
||||
boundary = "----FeedbackBoundary123"
|
||||
body_parts = []
|
||||
body_parts.append(f"--{boundary}\r\n".encode())
|
||||
body_parts.append(b'Content-Disposition: form-data; name="attachment"; filename="screenshot.png"\r\n')
|
||||
body_parts.append(b"Content-Type: image/png\r\n\r\n")
|
||||
body_parts.append(img_bytes)
|
||||
body_parts.append(f"\r\n--{boundary}--\r\n".encode())
|
||||
multipart_body = b"".join(body_parts)
|
||||
# Support single "image" or multiple "images" array
|
||||
images_b64 = data.get("images", [])
|
||||
single_image = data.get("image")
|
||||
if single_image:
|
||||
images_b64.insert(0, single_image)
|
||||
|
||||
img_req = urllib.request.Request(
|
||||
f"{GITEA_URL}/api/v1/repos/{REPO}/issues/{issue_number}/assets",
|
||||
data=multipart_body,
|
||||
headers={
|
||||
"Authorization": f"token {GITEA_TOKEN}",
|
||||
"Content-Type": f"multipart/form-data; boundary={boundary}",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
urllib.request.urlopen(img_req, timeout=15)
|
||||
except Exception as img_err:
|
||||
pass # Image upload failed but issue was created
|
||||
for idx, img_b64 in enumerate(images_b64):
|
||||
try:
|
||||
img_bytes = base64.b64decode(img_b64)
|
||||
filename = f"screenshot{'_' + str(idx + 1) if idx > 0 else ''}.png"
|
||||
boundary = f"----FeedbackBoundary{idx}"
|
||||
body_parts = []
|
||||
body_parts.append(f"--{boundary}\r\n".encode())
|
||||
body_parts.append(f'Content-Disposition: form-data; name="attachment"; filename="{filename}"\r\n'.encode())
|
||||
body_parts.append(b"Content-Type: image/png\r\n\r\n")
|
||||
body_parts.append(img_bytes)
|
||||
body_parts.append(f"\r\n--{boundary}--\r\n".encode())
|
||||
multipart_body = b"".join(body_parts)
|
||||
|
||||
img_req = urllib.request.Request(
|
||||
f"{GITEA_URL}/api/v1/repos/{REPO}/issues/{issue_number}/assets",
|
||||
data=multipart_body,
|
||||
headers={
|
||||
"Authorization": f"token {GITEA_TOKEN}",
|
||||
"Content-Type": f"multipart/form-data; boundary={boundary}",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
urllib.request.urlopen(img_req, timeout=15)
|
||||
except Exception:
|
||||
pass # Image upload failed but issue was created
|
||||
|
||||
handler._send_json({
|
||||
"ok": True,
|
||||
|
||||
Reference in New Issue
Block a user