모바일에서 6~7자리 숫자를 드래그하면 hitomi 이동 버튼을 제공하는 자동 크기 2단 리스트 형태의 UI를 화면 좌측 하단에 고정 표시하며, 모든 귀퉁이가 둥글고 닫기 버튼이 상단에 있습니다. 온/오프 버튼 제공.
// ==UserScript==
// @name 품번으로 hitomi 이동 (좌측 하단 라운딩, 상단 닫기, 온/오프)
// @namespace dendenmushi
// @version 4.7.1
// @description 모바일에서 6~7자리 숫자를 드래그하면 hitomi 이동 버튼을 제공하는 자동 크기 2단 리스트 형태의 UI를 화면 좌측 하단에 고정 표시하며, 모든 귀퉁이가 둥글고 닫기 버튼이 상단에 있습니다. 온/오프 버튼 제공.
// @author dendenmushi with Gemini
// @match *://*/*
// @license MIT
// @grant GM_openInTab
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
let draggedNumber = null;
let isFeatureEnabled = localStorage.getItem('dragFeatureEnabled') === 'true' || true; // 기본 On
GM_addStyle(`
#drag-feature-toggle {
position: fixed;
bottom: 20px;
right: 20px;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: rgba(128, 128, 128, 0.5); /* 기본 반투명 회색 */
color: white; /* 항상 흰색 H */
font-size: 1.5em;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 9999;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
text-transform: uppercase;
font-weight: bold;
}
#drag-button-list-container {
display: none;
position: fixed;
bottom: 20px; /* 아래 여백 조정 및 고정 */
left: 20px; /* 왼쪽 여백 조정 및 고정 */
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 10px;
border-radius: 10px; /* 모든 귀퉁이 라운딩 */
z-index: 10000;
text-align: left;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: flex-start; /* 왼쪽 정렬 */
width: auto; /* 내용에 따라 너비 자동 조정 */
max-width: 80vw; /* 최대 너비 제한 (필요에 따라 조정) */
}
#drag-button-list-container.show {
display: flex;
}
#drag-button-list-container button.close-button {
background: none;
border: none;
color: #ccc;
cursor: pointer;
font-size: 1em;
align-self: flex-end; /* 오른쪽 상단 배치 */
margin-bottom: 5px; /* 제목과의 간격 */
}
#drag-button-list-container h2 {
margin: 0 0 10px 0;
font-size: 1.1em;
width: 100%;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#drag-button-list-container a {
display: block;
background-color: #5cb85c;
color: white;
padding: 8px 15px;
text-decoration: none;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
margin-bottom: 5px;
width: 100%;
text-align: center;
box-sizing: border-box;
}
#toast-message {
position: fixed;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 10px 20px;
border-radius: 5px;
z-index: 9999;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
#toast-message.show {
opacity: 1;
}
`);
let toastTimeout;
function showToast(message) {
const toast = document.getElementById('toast-message') || document.createElement('div');
toast.id = 'toast-message';
toast.textContent = message;
document.body.appendChild(toast);
toast.classList.add('show');
clearTimeout(toastTimeout);
toastTimeout = setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => {
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
}, 300);
}, 1500);
}
function showButtonList(number) {
const container = document.getElementById('drag-button-list-container') || createButtonListContainer();
container.innerHTML = `
<button class="close-button">×</button>
<h2>${number}</h2>
<a href="https://hitomi.la/reader/${number}.html" target="_blank">hitomi 이동</a>
`;
container.classList.add('show');
document.body.appendChild(container);
const closeButton = container.querySelector('.close-button');
if (closeButton) {
closeButton.addEventListener('click', () => {
container.classList.remove('show');
});
}
}
function createButtonListContainer() {
const container = document.createElement('div');
container.id = 'drag-button-list-container';
return container;
}
document.addEventListener('touchend', function(event) {
if (isFeatureEnabled) {
const selectedText = window.getSelection().toString().trim();
const numberRegex = /^\d{6,7}$/;
if (numberRegex.test(selectedText)) {
draggedNumber = selectedText;
showButtonList(draggedNumber);
}
window.getSelection().removeAllRanges();
}
});
// 온/오프 버튼 생성
const toggleButton = document.createElement('div');
toggleButton.id = 'drag-feature-toggle';
toggleButton.textContent = 'H';
toggleButton.classList.toggle('enabled', isFeatureEnabled);
document.body.appendChild(toggleButton);
// 온/오프 버튼 클릭 이벤트 리스너
toggleButton.addEventListener('click', function() {
isFeatureEnabled = !isFeatureEnabled;
toggleButton.classList.toggle('enabled', isFeatureEnabled);
localStorage.setItem('dragFeatureEnabled', isFeatureEnabled); // 상태 저장
showToast(`드래그 기능이 ${isFeatureEnabled ? '활성화' : '비활성화'}되었습니다.`);
});
// 페이지 로드 시 버튼 초기 상태 설정
if (isFeatureEnabled) {
toggleButton.classList.add('enabled');
}
})();