Skip to content

Instantly share code, notes, and snippets.

@bravekingzhang
Last active February 29, 2024 05:12
Show Gist options
  • Save bravekingzhang/aa47fa43d1022bbcd1547979d3931e3a to your computer and use it in GitHub Desktop.
Save bravekingzhang/aa47fa43d1022bbcd1547979d3931e3a to your computer and use it in GitHub Desktop.
让notion支持插入图片
// ==UserScript==
// @name Image search for editor with giphy
// @namespace http://tampermonkey.net/
// @version 2024-02-28
// @description Search and insert images into Notion
// @author brzhang
// @match https://*/*
// @grant GM_setClipboard
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
function showSearchLoading() {
document.getElementById('imageSearchButton').innerHTML = 'Searching...';
document.getElementById('imageSearchButton').disabled = true;
// create a loading html element ,and put it in the search results
const loadingHtml = `<div id="imageSearchLoading" style="margin-top:10px;">Loading...</div>`;
document
.getElementById('imageSearchResults')
.insertAdjacentHTML('beforeend', loadingHtml);
}
// Function to create the search panel,center the panel on the screen ,close it when user clicks outside
function createSearchPanel() {
const panelHTML = `
<div
id="imageSearchPanel"
style="
display: flex;
flex-direction: column;
overflow: auto;
width: 500px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
background: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
"
>
<div
style="
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
"
>
<input
type="text"
id="imageSearchQuery"
placeholder="Search for images"
style="
width: calc(100% - 80px);
padding: 10px;
border-radius: 5px;
border: 1px solid #ccc;
box-sizing: border-box;
"
/>
<button
id="imageSearchButton"
style="
padding: 10px;
border: none;
background-color: #4caf50;
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
"
>
Search
</button>
</div>
<button
id="settingsButton"
style="
position: absolute;
top: 0;
left: 0;
margin-bottom: 10px;
border: none;
background-color: #007bff;
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
"
>
Settings
</button>
<button
id="closeButton"
style="
position: absolute;
top: 0;
right: 0;
margin-bottom: 10px;
border: none;
background-color: #dc3545;
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
"
>
X
</button>
<div
id="imageSearchResults"
style="
display: flex;
flex-wrap: wrap;
max-height: 500px;
overflow-y: auto;
"
></div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', panelHTML);
document
.getElementById('imageSearchButton')
.addEventListener('click', function() {
const query = document.getElementById('imageSearchQuery').value;
searchImages(query);
});
document.getElementById('imageSearchQuery').focus();
document
.getElementById('imageSearchQuery')
.addEventListener('keydown', function(event) {
// 检查是否是回退键被按下
if (event.key === 'Backspace') {
// 阻止事件的默认行为(在这里是删除前一个字符)
event.preventDefault();
// 停止事件继续传播
event.stopPropagation();
// 你可以在这里添加代码来手动处理输入框的文本删除逻辑
// 比如手动删除输入框中的最后一个字符
let currentValue = this.value;
this.value = currentValue.substring(0, currentValue.length - 1);
}
});
//copy parse for imageSearchQuery
document
.getElementById('imageSearchQuery')
.addEventListener('paste', function(event) {
event.preventDefault();
event.stopPropagation();
const text = event.clipboardData.getData('text/plain');
document.getElementById('imageSearchQuery').value = text;
});
document
.getElementById('closeButton')
.addEventListener('click', function() {
document.getElementById('imageSearchPanel').remove();
});
document
.getElementById('settingsButton')
.addEventListener('click', function() {
createSettingsPanel();
});
}
// Function to create the settings panel
function createSettingsPanel() {
// Check if the settings panel already exists
if (document.getElementById('settingsPanel')) {
return;
}
const settingsHTML = `
<div
id="settingsPanel"
style="
position: absolute;
top: 50%;
left: 50%;
width: max-content;
transform: translate(-50%, -50%);
z-index: 10000;
background: #fff;
padding: 10px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
"
>
<label for="api-key-input">Giphy API Key:<a href="https://developers.giphy.com">?</a></label>
<input
type="text"
id="api-key-input"
placeholder="Enter your API key"
style="
padding: 10px;
border-radius: 5px;
border: 1px solid #ccc;
box-sizing: border-box;
"
/>
<button
id="save-api-key"
style="
padding: 10px;
border: none;
background-color: #4caf50;
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
"
>
Save
</button>
<button
id="close-settings"
style="
padding: 10px;
border: none;
background-color: #dc3545;
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
"
>
Close
</button>
</div>
`;
document.body.insertAdjacentHTML('beforeend', settingsHTML);
const apiKey = GM_getValue('apiKey', '');
if (apiKey) {
document.getElementById('api-key-input').value = apiKey;
}
document
.getElementById('save-api-key')
.addEventListener('click', saveApiKey);
document
.getElementById('close-settings')
.addEventListener('click', function() {
document.getElementById('settingsPanel').remove();
});
document.getElementById('api-key-input').focus();
document
.getElementById('api-key-input')
.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
saveApiKey();
}
if (event.key === 'Backspace') {
// 阻止事件的默认行为(在这里是删除前一个字符)
event.preventDefault();
// 停止事件继续传播
event.stopPropagation();
// 你可以在这里添加代码来手动处理输入框的文本删除逻辑
// 比如手动删除输入框中的最后一个字符
let currentValue = this.value;
this.value = currentValue.substring(0, currentValue.length - 1);
}
});
//copy parse for apiKey
document
.getElementById('api-key-input')
.addEventListener('paste', function(event) {
event.preventDefault();
event.stopPropagation();
const text = event.clipboardData.getData('text/plain');
document.getElementById('api-key-input').value = text;
});
}
function saveApiKey() {
let apiKey = document.getElementById('api-key-input').value;
console.log('Saving API key:', apiKey);
//trim
apiKey = apiKey.trim();
//check apiKey
if (apiKey) {
GM_setValue('apiKey', apiKey);
alert('API Key saved successfully!');
} else {
alert('Please enter an API key.');
}
}
// Function to search for images (placeholder function, implement your API call here)
function searchImages(query) {
console.log('Searching for:', query);
const apiKey = GM_getValue('apiKey', '');
if (!apiKey) {
alert('Please enter an API key,by clicking the settings button.');
return;
}
// search for images from giphy API
const url = `https://api.giphy.com/v1/gifs/search?api_key=${apiKey}&q=${encodeURIComponent(
query
)}&limit=20&rating=g&lang=zh-CN&bundle=messaging_non_clips`;
fetch(url)
.then(response => response.json())
.then(data => {
console.log('API response:', data.data);
displayImages(data.data);
});
}
// Function to display image results
function displayImages(images) {
const resultsContainer = document.getElementById('imageSearchResults');
// resultsContainer remove all children
while (resultsContainer.firstChild) {
resultsContainer.removeChild(resultsContainer.firstChild);
}
resultsContainer.innerHTML = ''; // Clear previous results
// 对图片展示进行优化,增加过渡效果
images.forEach(image => {
const imgElem = document.createElement('img');
imgElem.src = image.images.original.url;
imgElem.style.width = '100px';
imgElem.style.height = '100px';
imgElem.style.margin = '5px';
imgElem.style.borderRadius = '5px';
imgElem.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
imgElem.style.transition = 'transform 0.3s ease';
imgElem.style.cursor = 'pointer';
imgElem.title = 'Click to copy image URL';
imgElem.addEventListener('mouseover', () => {
imgElem.style.transform = 'scale(1.1)';
});
imgElem.addEventListener('mouseout', () => {
imgElem.style.transform = 'scale(1)';
});
imgElem.addEventListener('click', () => {
GM_setClipboard(image.images.original.url);
// alert('Image URL copied to clipboard!');
});
resultsContainer.appendChild(imgElem);
});
}
// when user click command + shift + i, create the search panel
document.addEventListener('keydown', function(event) {
if (
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.code === 'KeyI'
) {
console.log('Search image clicked');
createSearchPanel();
}
});
// press esc to close the search panel
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
document.getElementById('imageSearchPanel').remove();
}
});
// press enter to search
document.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
const query = document.getElementById('imageSearchQuery').value;
if (!query) {
return;
}
searchImages(query);
event.preventDefault();
event.stopPropagation();
// 阻止默认行为
document.getElementById('imageSearchQuery').blur();
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment