Merge pull request #191 from feederbox826/main

Add CropperJS and Scene Cropper as JS plugins
This commit is contained in:
scruffynerf
2023-10-24 12:21:37 -04:00
committed by GitHub
5 changed files with 3745 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
name: Cropper.JS
description: Exports cropper.js functionality for JS/Userscripts
version: 1.6.1
ui:
css:
- cropper.css
javascript:
- cropper.js
# note - not minimized for more transparency around updates & diffs against source code
# https://github.com/fengyuanchen/cropperjs/tree/main/dist

View File

@@ -0,0 +1,308 @@
/*!
* Cropper.js v1.6.1
* https://fengyuanchen.github.io/cropperjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2023-09-17T03:44:17.565Z
*/
.cropper-container {
direction: ltr;
font-size: 0;
line-height: 0;
position: relative;
-ms-touch-action: none;
touch-action: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.cropper-container img {
backface-visibility: hidden;
display: block;
height: 100%;
image-orientation: 0deg;
max-height: none !important;
max-width: none !important;
min-height: 0 !important;
min-width: 0 !important;
width: 100%;
}
.cropper-wrap-box,
.cropper-canvas,
.cropper-drag-box,
.cropper-crop-box,
.cropper-modal {
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.cropper-wrap-box,
.cropper-canvas {
overflow: hidden;
}
.cropper-drag-box {
background-color: #fff;
opacity: 0;
}
.cropper-modal {
background-color: #000;
opacity: 0.5;
}
.cropper-view-box {
display: block;
height: 100%;
outline: 1px solid #39f;
outline-color: rgba(51, 153, 255, 0.75);
overflow: hidden;
width: 100%;
}
.cropper-dashed {
border: 0 dashed #eee;
display: block;
opacity: 0.5;
position: absolute;
}
.cropper-dashed.dashed-h {
border-bottom-width: 1px;
border-top-width: 1px;
height: calc(100% / 3);
left: 0;
top: calc(100% / 3);
width: 100%;
}
.cropper-dashed.dashed-v {
border-left-width: 1px;
border-right-width: 1px;
height: 100%;
left: calc(100% / 3);
top: 0;
width: calc(100% / 3);
}
.cropper-center {
display: block;
height: 0;
left: 50%;
opacity: 0.75;
position: absolute;
top: 50%;
width: 0;
}
.cropper-center::before,
.cropper-center::after {
background-color: #eee;
content: ' ';
display: block;
position: absolute;
}
.cropper-center::before {
height: 1px;
left: -3px;
top: 0;
width: 7px;
}
.cropper-center::after {
height: 7px;
left: 0;
top: -3px;
width: 1px;
}
.cropper-face,
.cropper-line,
.cropper-point {
display: block;
height: 100%;
opacity: 0.1;
position: absolute;
width: 100%;
}
.cropper-face {
background-color: #fff;
left: 0;
top: 0;
}
.cropper-line {
background-color: #39f;
}
.cropper-line.line-e {
cursor: ew-resize;
right: -3px;
top: 0;
width: 5px;
}
.cropper-line.line-n {
cursor: ns-resize;
height: 5px;
left: 0;
top: -3px;
}
.cropper-line.line-w {
cursor: ew-resize;
left: -3px;
top: 0;
width: 5px;
}
.cropper-line.line-s {
bottom: -3px;
cursor: ns-resize;
height: 5px;
left: 0;
}
.cropper-point {
background-color: #39f;
height: 5px;
opacity: 0.75;
width: 5px;
}
.cropper-point.point-e {
cursor: ew-resize;
margin-top: -3px;
right: -3px;
top: 50%;
}
.cropper-point.point-n {
cursor: ns-resize;
left: 50%;
margin-left: -3px;
top: -3px;
}
.cropper-point.point-w {
cursor: ew-resize;
left: -3px;
margin-top: -3px;
top: 50%;
}
.cropper-point.point-s {
bottom: -3px;
cursor: s-resize;
left: 50%;
margin-left: -3px;
}
.cropper-point.point-ne {
cursor: nesw-resize;
right: -3px;
top: -3px;
}
.cropper-point.point-nw {
cursor: nwse-resize;
left: -3px;
top: -3px;
}
.cropper-point.point-sw {
bottom: -3px;
cursor: nesw-resize;
left: -3px;
}
.cropper-point.point-se {
bottom: -3px;
cursor: nwse-resize;
height: 20px;
opacity: 1;
right: -3px;
width: 20px;
}
@media (min-width: 768px) {
.cropper-point.point-se {
height: 15px;
width: 15px;
}
}
@media (min-width: 992px) {
.cropper-point.point-se {
height: 10px;
width: 10px;
}
}
@media (min-width: 1200px) {
.cropper-point.point-se {
height: 5px;
opacity: 0.75;
width: 5px;
}
}
.cropper-point.point-se::before {
background-color: #39f;
bottom: -50%;
content: ' ';
display: block;
height: 200%;
opacity: 0;
position: absolute;
right: -50%;
width: 200%;
}
.cropper-invisible {
opacity: 0;
}
.cropper-bg {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
}
.cropper-hide {
display: block;
height: 0;
position: absolute;
width: 0;
}
.cropper-hidden {
display: none !important;
}
.cropper-move {
cursor: move;
}
.cropper-crop {
cursor: crosshair;
}
.cropper-disabled .cropper-drag-box,
.cropper-disabled .cropper-face,
.cropper-disabled .cropper-line,
.cropper-disabled .cropper-point {
cursor: not-allowed;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
// By ScruffyNerf
// Ported by feederbox826
(function () {
let cropping = false;
let cropper = null;
try {
const img = document.createElement('img');
new Cropper(img)
} catch (e) {
console.error("Cropper not loaded - please install 4. CropperJS from CommunityScripts")
}
try {
stash.getVersion()
} catch (e) {
console.error("Stash not loaded - please install 1. stashUserscriptLibrary from CommunityScripts")
}
function setupCropper() {
const cropBtnContainerId = "crop-btn-container";
if (document.getElementById(cropBtnContainerId)) return
const sceneId = window.location.pathname.replace('/scenes/', '').split('/')[0];
const sceneImage = document.querySelector("img.scene-cover")
var cropperModal = document.createElement("dialog");
cropperModal.style.width = "90%";
cropperModal.style.border = "none";
cropperModal.classList.add('bg-dark');
document.body.appendChild(cropperModal);
var cropperContainer = document.createElement("div");
cropperContainer.style.width = "100%";
cropperContainer.style.height = "auto";
cropperContainer.style.margin = "auto";
cropperModal.appendChild(cropperContainer);
var image = sceneImage.cloneNode();
image.style.display = "block";
image.style.maxWidth = "100%";
cropperContainer.appendChild(image);
var cropBtnContainer = document.createElement('div');
cropBtnContainer.setAttribute("id", cropBtnContainerId);
cropBtnContainer.classList.add('d-flex','flex-row','justify-content-center','align-items-center');
cropBtnContainer.style.gap = "10px";
cropperModal.appendChild(cropBtnContainer);
sceneImage.parentElement.parentElement.style.flexFlow = 'column';
const cropInfo = document.createElement('p');
cropInfo.style.all = "revert";
cropInfo.classList.add('text-white');
const cropStart = document.createElement('button');
cropStart.setAttribute("id", "crop-start");
cropStart.classList.add('btn', 'btn-primary');
cropStart.innerText = 'Crop Image';
cropStart.addEventListener('click', evt => {
cropping = true;
cropStart.style.display = 'none';
cropCancel.style.display = 'inline-block';
//const isVertical = image.naturalHeight > image.naturalWidth;
//const aspectRatio = isVertical ? 3/2 : NaN
const aspectRatio = NaN
cropper = new Cropper(image, {
viewMode: 1,
initialAspectRatio: aspectRatio,
movable: false,
rotatable: false,
scalable: false,
zoomable: false,
zoomOnTouch: false,
zoomOnWheel: false,
ready() {
cropAccept.style.display = 'inline-block';
},
crop(e) {
cropInfo.innerText = `X: ${Math.round(e.detail.x)}, Y: ${Math.round(e.detail.y)}, Width: ${Math.round(e.detail.width)}px, Height: ${Math.round(e.detail.height)}px`;
}
});
cropperModal.showModal();
});
sceneImage.parentElement.appendChild(cropStart);
const cropAccept = document.createElement('button');
cropAccept.setAttribute("id", "crop-accept");
cropAccept.classList.add('btn', 'btn-success', 'mr-2');
cropAccept.innerText = 'OK';
cropAccept.addEventListener('click', async evt => {
cropping = false;
cropStart.style.display = 'inline-block';
cropAccept.style.display = 'none';
cropCancel.style.display = 'none';
cropInfo.innerText = '';
const reqData = {
"operationName": "SceneUpdate",
"variables": {
"input": {
"cover_image": cropper.getCroppedCanvas().toDataURL(),
"id": sceneId
}
},
"query": `mutation SceneUpdate($input: SceneUpdateInput!) {
sceneUpdate(input: $input) {
id
}
}`
}
await stash.callGQL(reqData);
reloadImg(image.src);
cropper.destroy();
cropperModal.close("cropAccept");
});
cropBtnContainer.appendChild(cropAccept);
const cropCancel = document.createElement('button');
cropCancel.setAttribute("id", "crop-accept");
cropCancel.classList.add('btn', 'btn-danger');
cropCancel.innerText = 'Cancel';
cropCancel.addEventListener('click', evt => {
cropping = false;
cropStart.style.display = 'inline-block';
cropAccept.style.display = 'none';
cropCancel.style.display = 'none';
cropInfo.innerText = '';
cropper.destroy();
cropperModal.close("cropCancel");
});
cropBtnContainer.appendChild(cropCancel);
cropAccept.style.display = 'none';
cropCancel.style.display = 'none';
cropBtnContainer.appendChild(cropInfo);
}
stash.addEventListener('page:scene', function () {
waitForElementId('scene-edit-details', setupCropper);
});
})();

View File

@@ -0,0 +1,7 @@
name: Scene Cover Cropper
description: Crop Scene Cover Images
version: 1.0
ui:
css:
javascript:
- sceneCoverCropper.js