diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index 26a43dbef..f4bb2aa50 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -60,6 +60,9 @@ function RemoteFunctions(config = {}) { const AUTO_SCROLL_SPEED = 12; // pixels per scroll const AUTO_SCROLL_EDGE_SIZE = 0.05; // 5% of viewport height (either top/bottom) + // to track the state as we want to have a selected state for image gallery + let imageGallerySelected = false; + /** * this function is responsible to auto scroll the live preview when * dragging an element to the viewport edges @@ -128,8 +131,8 @@ function RemoteFunctions(config = {}) { if(element && // element should exist element.hasAttribute("data-brackets-id") && // should have the data-brackets-id attribute - element.tagName !== "BODY" && // shouldn't be the body tag - element.tagName !== "HTML" && // shouldn't be the HTML tag + element.tagName.toLowerCase() !== "body" && // shouldn't be the body tag + element.tagName.toLowerCase() !== "html" && // shouldn't be the HTML tag !_isInsideHeadTag(element)) { // shouldn't be inside the head tag like meta tags and all return true; } @@ -142,9 +145,22 @@ function RemoteFunctions(config = {}) { function _isInsideHeadTag(element) { let parent = element; while (parent && parent !== window.document) { - if (parent.tagName === "HEAD") { + if (parent.tagName.toLowerCase() === "head") { // allow
`; this._shadow = shadow; @@ -1688,9 +1907,9 @@ function RemoteFunctions(config = {}) { .phoenix-ai-prompt-box { position: absolute !important; - background: white !important; + background: #3C3F41 !important; border: 1px solid #4285F4 !important; - border-radius: 8px !important; + border-radius: 4px !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important; font-family: Arial, sans-serif !important; z-index: 2147483647 !important; @@ -1707,55 +1926,56 @@ function RemoteFunctions(config = {}) { width: 100% !important; height: ${boxHeight}px !important; border: none !important; - border-radius: 8px !important; + border-radius: 4px 4px 0 0 !important; padding: 12px 40px 12px 16px !important; font-size: 14px !important; font-family: Arial, sans-serif !important; resize: none !important; outline: none !important; box-sizing: border-box !important; - background: #f9f9f9 !important; + background: transparent !important; + color: #c5c5c5 !important; + transition: background 0.2s ease !important; } .phoenix-ai-prompt-textarea:focus { - background: white !important; + background: rgba(255, 255, 255, 0.03) !important; } .phoenix-ai-prompt-textarea::placeholder { - color: #999 !important; + color: #a0a0a0 !important; + opacity: 0.7 !important; } .phoenix-ai-prompt-send-button { - width: 28px !important; - height: 28px !important; - border: none !important; - border-radius: 50% !important; - background: #4285F4 !important; - color: white !important; + background-color: transparent !important; + border: 1px solid transparent !important; + color: #a0a0a0 !important; + border-radius: 4px !important; cursor: pointer !important; + padding: 3px 6px !important; display: flex !important; align-items: center !important; justify-content: center !important; font-size: 14px !important; - transition: background-color 0.2s !important; - line-height: 0.5 !important; + transition: all 0.2s ease !important; } .phoenix-ai-prompt-send-button:hover:not(:disabled) { - background: #4285F4 !important; + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; } .phoenix-ai-prompt-send-button:disabled { - background: #dadce0 !important; - color: #9aa0a6 !important; + opacity: 0.5 !important; cursor: not-allowed !important; } .phoenix-ai-bottom-controls { - border-top: 1px solid #e0e0e0 !important; + border-top: 1px solid rgba(255,255,255,0.14) !important; padding: 8px 16px !important; - background: #f9f9f9 !important; - border-radius: 0 0 8px 8px !important; + background: transparent !important; + border-radius: 0 0 4px 4px !important; display: flex !important; align-items: center !important; justify-content: space-between !important; @@ -1763,16 +1983,30 @@ function RemoteFunctions(config = {}) { .phoenix-ai-model-select { padding: 4px 8px !important; - border: 1px solid #ddd !important; + border: 1px solid transparent !important; border-radius: 4px !important; font-size: 12px !important; - background: white !important; + background: transparent !important; + color: #a0a0a0 !important; outline: none !important; cursor: pointer !important; + transition: all 0.2s ease !important; + } + + .phoenix-ai-model-select:hover { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; } .phoenix-ai-model-select:focus { - border-color: #4285F4 !important; + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; + } + + .phoenix-ai-model-select option { + background: #000 !important; + color: #fff !important; + padding: 4px 8px !important; } `; @@ -1791,7 +2025,7 @@ function RemoteFunctions(config = {}) { @@ -1913,13 +2147,80 @@ function RemoteFunctions(config = {}) { }; // image ribbon gallery cache, to store the last query and its results - // then next time we can load it from cache itself instead of making a new API call + const CACHE_EXPIRY_TIME = 168 * 60 * 60 * 1000; // 7 days, might need to revise this... + const CACHE_MAX_IMAGES = 50; // max number of images that we store in the localStorage const _imageGalleryCache = { - currentQuery: null, - allImages: [], - totalPages: 1, - currentPage: 1, - maxImages: 50 + get currentQuery() { + const data = this._getFromStorage(); + return data ? data.currentQuery : null; + }, + set currentQuery(val) { + this._updateStorage({currentQuery: val}); + }, + + get allImages() { + const data = this._getFromStorage(); + return data ? data.allImages : []; + }, + set allImages(val) { + this._updateStorage({allImages: val}); + }, + + get totalPages() { + const data = this._getFromStorage(); + return data ? data.totalPages : 1; + }, + set totalPages(val) { + this._updateStorage({totalPages: val}); + }, + + get currentPage() { + const data = this._getFromStorage(); + return data ? data.currentPage : 1; + }, + set currentPage(val) { + this._updateStorage({currentPage: val}); + }, + + + _getFromStorage() { + try { + const data = window.localStorage.getItem('imageGalleryCache'); + if (!data) { return null; } + + const parsed = JSON.parse(data); + + if (Date.now() > parsed.expires) { + window.localStorage.removeItem('imageGalleryCache'); + return null; + } + + return parsed; + } catch (error) { + return null; + } + }, + + _updateStorage(updates) { + try { + const current = this._getFromStorage() || {}; + const newData = { + ...current, + ...updates, + expires: Date.now() + CACHE_EXPIRY_TIME + }; + window.localStorage.setItem('imageGalleryCache', JSON.stringify(newData)); + } catch (error) { + if (error.name === 'QuotaExceededError') { + try { + window.localStorage.removeItem('imageGalleryCache'); + window.localStorage.setItem('imageGalleryCache', JSON.stringify(updates)); + } catch (retryError) { + console.error('Failed to save image cache even after clearing:', retryError); + } + } + } + } }; /** @@ -1934,8 +2235,6 @@ function RemoteFunctions(config = {}) { this.allImages = []; this.imagesPerPage = 10; this.scrollPosition = 0; - this.maxWidth = '800px'; // when current image dimension is not defined we use this as unsplash images are very large - this.maxHeight = '600px'; this.create(); } @@ -1953,7 +2252,7 @@ function RemoteFunctions(config = {}) { left: 0 !important; right: 0 !important; width: 100vw !important; - background: linear-gradient(180deg, rgba(12,14,20,0.0), rgba(12,14,20,0.7)) !important; + background: #3C3F41 !important; z-index: 2147483647 !important; display: flex !important; font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial !important; @@ -1963,11 +2262,7 @@ function RemoteFunctions(config = {}) { .phoenix-ribbon-container { width: 100% !important; height: 156px !important; - background: rgba(255, 255, 255, 0.3) !important; - backdrop-filter: blur(10px) !important; - -webkit-backdrop-filter: blur(10px) !important; border: 1px solid rgba(255, 255, 255, 0.2) !important; - border-radius: 12px !important; position: relative !important; } @@ -1977,7 +2272,7 @@ function RemoteFunctions(config = {}) { overflow: hidden !important; scroll-behavior: smooth !important; padding: 6px !important; - top: 34px !important; + top: 30px !important; } .phoenix-ribbon-row { @@ -2020,7 +2315,6 @@ function RemoteFunctions(config = {}) { color: #eaeaf0 !important; background: rgba(21,25,36,0.65) !important; cursor: pointer !important; - backdrop-filter: blur(8px) !important; font-size: 20px !important; font-weight: 600 !important; user-select: none !important; @@ -2066,87 +2360,164 @@ function RemoteFunctions(config = {}) { font-size: 14px !important; } + .phoenix-loading-more { + display: flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 120px !important; + height: 116px !important; + margin-left: 2px !important; + background: rgba(255,255,255,0.03) !important; + border-radius: 8px !important; + color: #e8eaf0 !important; + font-size: 12px !important; + border: 1px dashed rgba(255,255,255,0.1) !important; + } + .phoenix-ribbon-header { display: flex !important; width: 100% !important; position: absolute !important; - top: 5px !important; + top: 7px !important; } .phoenix-ribbon-header-left { width: 80% !important; display: flex !important; + align-items: center !important; } .phoenix-ribbon-header-right { width: 20% !important; display: flex !important; justify-content: flex-end !important; + align-items: center !important; } .phoenix-ribbon-search { display: flex !important; - align-items: center !important; - background: rgba(0,0,0,0.5) !important; - padding: 5px !important; - border-radius: 5px !important; + align-items: stretch !important; + border-radius: 6px !important; margin-left: 8px !important; + border: 1px solid rgba(255,255,255,0.14) !important; + } + + .phoenix-ribbon-search:hover { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; + } + + .phoenix-ribbon-search:focus-within { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; } .phoenix-ribbon-search input { background: transparent !important; border: none !important; outline: none !important; - color: white !important; - width: 200px !important; + color: #c5c5c5 !important; + width: 150px !important; + padding: 4px 8px !important; + border-radius: 4px 0 0 4px !important; + transition: background 0.2s ease !important; + } + + .phoenix-ribbon-search input:focus { + background: rgba(255, 255, 255, 0.03) !important; } .phoenix-ribbon-search input::placeholder { - color: rgba(255, 255, 255, 0.7) !important; - opacity: 1 !important; + color: #a0a0a0 !important; + opacity: 0.7 !important; } .phoenix-ribbon-search input::-webkit-input-placeholder { - color: rgba(255, 255, 255, 0.7) !important; + color: #a0a0a0 !important; + opacity: 0.7 !important; } .phoenix-ribbon-search input::-moz-placeholder { - color: rgba(255, 255, 255, 0.7) !important; - opacity: 1 !important; + color: #a0a0a0 !important; + opacity: 0.7 !important; } .phoenix-ribbon-search-btn { - background: none !important; - border: none !important; - color: #6aa9ff !important; + background: transparent !important; + border: 1px solid transparent !important; + border-left: 1px solid gray !important; + color: #a0a0a0 !important; cursor: pointer !important; + padding: 2px 6px !important; + border-radius: 0 4px 4px 0 !important; + font-size: 12px !important; + font-weight: 500 !important; + transition: all 0.2s ease !important; + margin-left: 0 !important; + } + + .phoenix-ribbon-search-btn:hover { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; } .phoenix-ribbon-select { - margin-left: 10px !important; + margin-left: 4px !important; } .phoenix-select-image-btn { - background: gray !important; - border: 1px solid rgba(255, 255, 255, 0.2) !important; - color: #fff !important; - padding: 2px 4px !important; - border-radius: 6px !important; - font-size: 12px !important; + background-color: transparent !important; + border: 1px solid transparent !important; + color: #a0a0a0 !important; + border-radius: 4px !important; cursor: pointer !important; - transition: all 0.2s ease !important; + padding: 3px 6px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + } + + .phoenix-select-image-btn:hover { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; + } + + .phoenix-ribbon-folder-settings { + background-color: transparent !important; + border: 1px solid transparent !important; + color: #a0a0a0 !important; + border-radius: 4px !important; + cursor: pointer !important; + margin-right: 2px !important; + padding: 3px 6px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + } + + .phoenix-ribbon-folder-settings:hover { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; } .phoenix-ribbon-close { - background: rgba(0,0,0,0.5) !important; - border: none !important; - color: white !important; + background-color: transparent !important; + border: 1px solid transparent !important; + color: #a0a0a0 !important; + border-radius: 4px !important; cursor: pointer !important; - padding: 4px 8px !important; - border-radius: 3px !important; + padding: 3px 6px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; margin-right: 16px !important; } + .phoenix-ribbon-close:hover { + border: 1px solid rgba(0, 0, 0, 0.24) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; + } + .phoenix-ribbon-attribution { position: absolute !important; bottom: 6px !important; @@ -2274,26 +2645,28 @@ function RemoteFunctions(config = {}) {{{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_DESCRIPTION}}
+ + + + + ++ {{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_HELP}} +
+ +