mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 09:19:42 +02:00
fix(uploads): show the server's reason when a prompt upload fails
A failed upload only showed a count, so a remote session's refused upload read as a mystery instead of a rule the user could act on. The server already returns the reason in its error envelope and the per-file error carries it, so I surface the first one in the toast. One reason is enough when a whole batch fails for the same cause.
This commit is contained in:
@@ -150,6 +150,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
const total = files.length;
|
||||
let done = 0;
|
||||
let failed = 0;
|
||||
let failReason = ''; // first server reason, shown in the toast so a failure is not just a count
|
||||
const results = new Array(total); // preserve selection order for insertion
|
||||
const progress = () =>
|
||||
this.showToast(`Uploading ${Math.min(done + 1, total)}/${total} image${total > 1 ? 's' : ''}…`, 'info');
|
||||
@@ -173,6 +174,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
results[i] = await this._uploadPasteImage(sessionId, normalized);
|
||||
} catch (err) {
|
||||
failed++;
|
||||
if (!failReason && err && err.message) failReason = err.message;
|
||||
console.warn('Image upload failed:', err);
|
||||
results[i] = null;
|
||||
} finally {
|
||||
@@ -196,7 +198,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
// Final status: successes, plus any failures / cap so nothing is silent.
|
||||
const parts = [];
|
||||
if (paths.length > 0) parts.push(`${paths.length} image${paths.length > 1 ? 's' : ''} ready`);
|
||||
if (failed > 0) parts.push(`${failed} failed`);
|
||||
if (failed > 0) parts.push(failReason ? `${failed} failed: ${failReason}` : `${failed} failed`);
|
||||
if (capped) parts.push(`max ${this._maxBatchImages} per batch`);
|
||||
const tone = paths.length > 0 ? (failed > 0 || capped ? 'info' : 'success') : 'error';
|
||||
this.showToast(parts.join(' · ') || 'No images uploaded', tone);
|
||||
|
||||
@@ -238,4 +238,16 @@ describe('image upload insertion policy', () => {
|
||||
expect(app._uploadPasteImage).toHaveBeenCalledWith('session-b', { path: '/tmp/pane-b.png' });
|
||||
expect(app._sendInputAsync).toHaveBeenCalledWith('session-b', '/tmp/pane-b.png', { useMux: true });
|
||||
});
|
||||
|
||||
it('shows the server reason in the toast when an upload fails', async () => {
|
||||
const app = loadImageInputApp();
|
||||
const reason = 'Prompt uploads are not supported for remote (SSH) sessions';
|
||||
app._uploadPasteImage = vi.fn(async () => {
|
||||
throw new Error(reason);
|
||||
});
|
||||
|
||||
await app._uploadAndInsertImages([{ path: '/tmp/shot.png' }]);
|
||||
|
||||
expect(app.showToast).toHaveBeenCalledWith(`1 failed: ${reason}`, 'error');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user