Skip to content

Commit 043e962

Browse files
devvaannshabose
authored andcommitted
fix: architectural issue with code flow on image downloads
1 parent e55264a commit 043e962

File tree

2 files changed

+108
-31
lines changed

2 files changed

+108
-31
lines changed

src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3162,18 +3162,9 @@ function RemoteFunctions(config = {}) {
31623162
const extnName = ".jpg";
31633163

31643164
const downloadUrl = image.url || image.thumb_url;
3165+
const downloadLocation = image.download_location;
31653166

3166-
// we need to make a req to the download endpoint
3167-
// its required by the Unsplash API guidelines to track downloads for photographers
3168-
// this is just a tracking call, we don't need to wait for the response
3169-
if (image.download_location) {
3170-
fetch(`https://images.phcode.dev/api/images/download?download_location=${encodeURIComponent(image.download_location)}`)
3171-
.catch(error => {
3172-
console.error('download tracking failed:', error);
3173-
});
3174-
}
3175-
3176-
this._useImage(downloadUrl, filename, extnName, false, thumbDiv);
3167+
this._useImage(downloadUrl, filename, extnName, false, thumbDiv, downloadLocation);
31773168
});
31783169

31793170
thumbDiv.appendChild(img);
@@ -3213,9 +3204,9 @@ function RemoteFunctions(config = {}) {
32133204
return `${cleanSearchTerm}-by-${cleanPhotographerName}`;
32143205
},
32153206

3216-
_useImage: function(imageUrl, filename, extnName, isLocalFile, thumbDiv) {
3217-
// send the message to the editor instance to save the image and update the source code
3207+
_useImage: function(imageUrl, filename, extnName, isLocalFile, thumbDiv, downloadLocation) {
32183208
const tagId = this.element.getAttribute("data-brackets-id");
3209+
const downloadId = Date.now() + Math.random();
32193210

32203211
const messageData = {
32213212
livePreviewEditEnabled: true,
@@ -3224,7 +3215,9 @@ function RemoteFunctions(config = {}) {
32243215
filename: filename,
32253216
extnName: extnName,
32263217
element: this.element,
3227-
tagId: Number(tagId)
3218+
tagId: Number(tagId),
3219+
downloadLocation: downloadLocation,
3220+
downloadId: downloadId
32283221
};
32293222

32303223
// if this is a local file we need some more data before sending it to the editor
@@ -3239,15 +3232,12 @@ function RemoteFunctions(config = {}) {
32393232
messageData.imageData = byteNumbers;
32403233
}
32413234

3242-
window._Brackets_MessageBroker.send(messageData);
3235+
_activeDownloads.set(downloadId, {
3236+
thumbDiv: thumbDiv,
3237+
timestamp: Date.now()
3238+
});
32433239

3244-
// if thumbDiv is provided, hide the download indicator after a reasonable timeout
3245-
// this is to make sure that the indicator is always removed even if there's no explicit success callback
3246-
if (thumbDiv) {
3247-
setTimeout(() => {
3248-
this._hideDownloadIndicator(thumbDiv);
3249-
}, 3000);
3250-
}
3240+
window._Brackets_MessageBroker.send(messageData);
32513241
},
32523242

32533243
_handleLocalImageSelection: function(file) {
@@ -3640,6 +3630,41 @@ function RemoteFunctions(config = {}) {
36403630
var _setup = false;
36413631
var _hoverLockTimer = null;
36423632

3633+
const DOWNLOAD_EVENTS = {
3634+
STARTED: 'downloadStarted',
3635+
COMPLETED: 'downloadCompleted',
3636+
CANCELLED: 'downloadCancelled',
3637+
ERROR: 'downloadError'
3638+
};
3639+
3640+
let _activeDownloads = new Map();
3641+
3642+
function handleDownloadEvent(eventType, data) {
3643+
const downloadId = data && data.downloadId;
3644+
if (!downloadId) {
3645+
return;
3646+
}
3647+
3648+
const download = _activeDownloads.get(downloadId);
3649+
if (!download) {
3650+
return;
3651+
}
3652+
3653+
switch (eventType) {
3654+
case DOWNLOAD_EVENTS.STARTED:
3655+
break;
3656+
3657+
case DOWNLOAD_EVENTS.COMPLETED:
3658+
case DOWNLOAD_EVENTS.CANCELLED:
3659+
case DOWNLOAD_EVENTS.ERROR:
3660+
if (_imageRibbonGallery && download.thumbDiv) {
3661+
_imageRibbonGallery._hideDownloadIndicator(download.thumbDiv);
3662+
}
3663+
_activeDownloads.delete(downloadId);
3664+
break;
3665+
}
3666+
}
3667+
36433668
function onMouseOver(event) {
36443669
if (_validEvent(event)) {
36453670
const element = event.target;
@@ -4660,6 +4685,7 @@ function RemoteFunctions(config = {}) {
46604685
"hasVisibleLivePreviewBoxes" : hasVisibleLivePreviewBoxes,
46614686
"dismissUIAndCleanupState" : dismissUIAndCleanupState,
46624687
"enableHoverListeners" : enableHoverListeners,
4663-
"registerHandlers" : registerHandlers
4688+
"registerHandlers" : registerHandlers,
4689+
"handleDownloadEvent" : handleDownloadEvent
46644690
};
46654691
}

src/LiveDevelopment/LivePreviewEdit.js

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ define(function (require, exports, module) {
4343
// state manager key, to save the download location of the image
4444
const IMAGE_DOWNLOAD_FOLDER_KEY = "imageGallery.downloadFolder";
4545

46+
const DOWNLOAD_EVENTS = {
47+
STARTED: 'downloadStarted',
48+
COMPLETED: 'downloadCompleted',
49+
CANCELLED: 'downloadCancelled',
50+
ERROR: 'downloadError'
51+
};
52+
4653
const KernalModeTrust = window.KernalModeTrust;
4754
if(!KernalModeTrust){
4855
// integrated extensions will have access to kernal mode, but not external extensions
@@ -686,6 +693,32 @@ define(function (require, exports, module) {
686693
}
687694
}
688695

696+
function _sendDownloadStatusToBrowser(eventType, data) {
697+
const currLiveDoc = LiveDevMultiBrowser.getCurrentLiveDoc();
698+
if (currLiveDoc && currLiveDoc.protocol && currLiveDoc.protocol.evaluate) {
699+
const dataJson = JSON.stringify(data || {});
700+
const evalString = `_LD.handleDownloadEvent('${eventType}', ${dataJson})`;
701+
currLiveDoc.protocol.evaluate(evalString);
702+
}
703+
}
704+
705+
function _handleDownloadError(error, downloadId) {
706+
console.error('something went wrong while download the image. error:', error);
707+
if (downloadId) {
708+
_sendDownloadStatusToBrowser(DOWNLOAD_EVENTS.ERROR, { downloadId: downloadId });
709+
}
710+
}
711+
712+
function _trackDownload(downloadLocation) {
713+
if (!downloadLocation) {
714+
return;
715+
}
716+
fetch(`https://images.phcode.dev/api/images/download?download_location=${encodeURIComponent(downloadLocation)}`)
717+
.catch(error => {
718+
console.error('download tracking failed:', error);
719+
});
720+
}
721+
689722
/**
690723
* Helper function to update image src attribute and dismiss ribbon gallery
691724
*
@@ -717,16 +750,18 @@ define(function (require, exports, module) {
717750
* @param {Directory} projectRoot - the project root in which the image is to be saved
718751
*/
719752
function _handleUseThisImageLocalFiles(message, filename, projectRoot) {
720-
const { tagId, imageData } = message;
753+
const { tagId, imageData, downloadLocation, downloadId } = message;
721754

722755
const uint8Array = new Uint8Array(imageData);
723756
const targetPath = projectRoot.fullPath + filename;
724757

725758
window.fs.writeFile(targetPath, window.Filer.Buffer.from(uint8Array),
726759
{ encoding: window.fs.BYTE_ARRAY_ENCODING }, (err) => {
727760
if (err) {
728-
console.error('Failed to save image:', err);
761+
_handleDownloadError(err, downloadId);
729762
} else {
763+
_trackDownload(downloadLocation);
764+
_sendDownloadStatusToBrowser(DOWNLOAD_EVENTS.COMPLETED, { downloadId });
730765
_updateImageAndDismissRibbon(tagId, targetPath, filename);
731766
}
732767
});
@@ -739,7 +774,7 @@ define(function (require, exports, module) {
739774
* @param {Directory} projectRoot - the project root in which the image is to be saved
740775
*/
741776
function _handleUseThisImageRemote(message, filename, projectRoot) {
742-
const { imageUrl, tagId } = message;
777+
const { imageUrl, tagId, downloadLocation, downloadId } = message;
743778

744779
fetch(imageUrl)
745780
.then(response => {
@@ -755,14 +790,16 @@ define(function (require, exports, module) {
755790
window.fs.writeFile(targetPath, window.Filer.Buffer.from(uint8Array),
756791
{ encoding: window.fs.BYTE_ARRAY_ENCODING }, (err) => {
757792
if (err) {
758-
console.error('Failed to save image:', err);
793+
_handleDownloadError(err, downloadId);
759794
} else {
795+
_trackDownload(downloadLocation);
796+
_sendDownloadStatusToBrowser(DOWNLOAD_EVENTS.COMPLETED, { downloadId });
760797
_updateImageAndDismissRibbon(tagId, targetPath, filename);
761798
}
762799
});
763800
})
764801
.catch(error => {
765-
console.error('Failed to fetch image:', error);
802+
_handleDownloadError(error, downloadId);
766803
});
767804
}
768805

@@ -779,6 +816,10 @@ define(function (require, exports, module) {
779816
return;
780817
}
781818

819+
if (message.downloadId) {
820+
_sendDownloadStatusToBrowser(DOWNLOAD_EVENTS.STARTED, { downloadId: message.downloadId });
821+
}
822+
782823
const filename = message.filename;
783824
const extnName = message.extnName || "jpg";
784825

@@ -793,11 +834,17 @@ define(function (require, exports, module) {
793834
// the directory name that user wrote, first check if it exists or not
794835
// if it doesn't exist we create it and then download the image inside it
795836
targetDir.exists((err, exists) => {
796-
if (err) { return; }
837+
if (err) {
838+
_handleDownloadError(err, message.downloadId);
839+
return;
840+
}
797841

798842
if (!exists) {
799843
targetDir.create((err) => {
800-
if (err) { return; }
844+
if (err) {
845+
_handleDownloadError(err, message.downloadId);
846+
return;
847+
}
801848
_downloadImageToDirectory(message, filename, extnName, targetDir);
802849
});
803850
} else {
@@ -1143,6 +1190,10 @@ define(function (require, exports, module) {
11431190
if (message) {
11441191
_downloadToFolder(message, folderPath);
11451192
}
1193+
} else {
1194+
if (message && message.downloadId) {
1195+
_sendDownloadStatusToBrowser(DOWNLOAD_EVENTS.CANCELLED, { downloadId: message.downloadId });
1196+
}
11461197
}
11471198
dialog.close();
11481199
});
@@ -1188,7 +1239,7 @@ define(function (require, exports, module) {
11881239
_handleUseThisImageRemote(message, uniqueFilename, targetDir);
11891240
}
11901241
}).catch(error => {
1191-
console.error('Something went wrong when trying to use this image', error);
1242+
_handleDownloadError(error, message.downloadId);
11921243
});
11931244
}
11941245

0 commit comments

Comments
 (0)