- Joined
- May 8, 2022
I think it should be obvious to anyone that I am not a programmer, but I do want to try to get into it as some sort of hobby. It's not something I want to devote my life but I like making little neat shit like this. i made a thread before about this, but I deleted it because I realized that after making the add-on, null uses xenforo 2.0, and not xenforo 1.0

KiwiNail is the final solution to thumbnailing. KiwiNail takes images from your clipboard and automatically resizes them into thumbnail format. It was originally meant for only Null, but I am okay with everyone using it.
The issue I am having with the add-on is that, despite injecting the scripts into the message_box template and the create_thread template, and adding error logs. XenForo refuses to read clipboard data. I've tried just about narrowing everything down.
I've even tried writing a custom .js script specifically for this, but no dice.
Everything works as intended. HOWEVER, XenForo cannot detect the getPaste() function nor read any clipboard image data. I've tried using jQuery and Xenforo's own system, but I don't know what I'm missing. I've tried using AI as a way to help, but there's nothing there.
CODE:
Editor.php
editor.js
Attachment.php
Addon.json

KiwiNail is the final solution to thumbnailing. KiwiNail takes images from your clipboard and automatically resizes them into thumbnail format. It was originally meant for only Null, but I am okay with everyone using it.
The issue I am having with the add-on is that, despite injecting the scripts into the message_box template and the create_thread template, and adding error logs. XenForo refuses to read clipboard data. I've tried just about narrowing everything down.
I've even tried writing a custom .js script specifically for this, but no dice.
JavaScript:
!function($, window, document, _undefined) {
"use strict";
XF.EditorPasteHandler = XF.Element.newHandler({
options: {},
init: function() {
console.log('EditorPasteHandler initialized');
this.$target.on('paste', XF.proxy(this, 'onPaste'));
},
onPaste: function(e) {
console.log('Paste event fired at ' + new Date().toISOString());
var clipboardData = e.originalEvent.clipboardData || window.clipboardData;
if (!clipboardData || !clipboardData.items) {
console.log('No clipboard data available');
return;
}
var items = clipboardData.items;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') === 0) {
var blob = items[i].getAsFile();
if (blob) {
console.log('Image detected, size: ' + blob.size + ' bytes');
this.uploadImage(blob);
e.preventDefault();
break;
}
}
}
},
uploadImage: function(blob) {
var formData = new FormData();
formData.append('upload', blob);
XF.ajax('POST', XF.canonicalizeUrl('index.php?editor/paste'), formData,
XF.proxy(this, 'uploadSuccess'),
{ contentType: false, processData: false }
).fail(function(xhr) {
console.error('Upload failed: ' + (xhr.responseText || 'Unknown error'));
});
},
uploadSuccess: function(data) {
console.log('Upload success: ' + JSON.stringify(data));
if (data.html) {
console.log('Inserting BB code: ' + data.html);
var editor = this.$target.data('xf-editor');
if (editor) {
editor.insertContent(data.html);
} else {
console.error('Editor instance not found');
}
}
}
});
XF.Element.register('editor-paste-handler', 'XF.EditorPasteHandler');
}(jQuery, window, document);
Everything works as intended. HOWEVER, XenForo cannot detect the getPaste() function nor read any clipboard image data. I've tried using jQuery and Xenforo's own system, but I don't know what I'm missing. I've tried using AI as a way to help, but there's nothing there.
CODE:
Editor.php
PHP:
<?php
namespace KiwiNail\UploadImagePaste\XF\Pub\Controller;
use XF\Mvc\ParameterBag;
class Editor extends XFCP_Editor
{
public function actionPaste(ParameterBag $params)
{
// Force logging to a specific file for testing
$logFile = \XF::app()->get('config')['internalDataPath'] . '/paste_log.txt';
file_put_contents($logFile, "actionPaste started at " . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
$upload = $this->request->getFile('upload');
if (!$upload) {
file_put_contents($logFile, "No file uploaded.\n", FILE_APPEND);
return $this->error(\XF::phrase('no_file_uploaded_or_file_is_not_valid_image'));
}
file_put_contents($logFile, "Upload received: " . $upload->getFileName() . " (" . $upload->getFileSize() . " bytes)\n", FILE_APPEND);
$handler = $this->getAttachmentHandler('post');
$context = ['content_type' => 'post', 'content_id' => 0];
$manipulator = $this->service('XF:Attachment\Manipulator', $handler, $context);
$attachment = $manipulator->upload($upload);
if (!$attachment) {
file_put_contents($logFile, "Attachment upload failed.\n", FILE_APPEND);
return $this->error(\XF::phrase('attachment_upload_failed'));
}
file_put_contents($logFile, "Attachment uploaded, ID: " . $attachment->attachment_id . "\n", FILE_APPEND);
// Thumbnail generation
$thumbW = 250;
$thumbH = 250;
$thumbnailDir = \XF::app()->get('config')['internalDataPath'] . '/attachments/thumbs/';
$thumbnailPath = $thumbnailDir . $attachment->attachment_id . '.jpg';
if (!file_exists($thumbnailDir)) {
mkdir($thumbnailDir, 0777, true);
file_put_contents($logFile, "Created thumbs directory: " . $thumbnailDir . "\n", FILE_APPEND);
}
$image = \XF::app()->imageManager()->imageFromFile($attachment->getData()['temp_file']);
if ($image) {
$image->resizeAndCrop($thumbW, $thumbH);
$image->save($thumbnailPath, IMAGETYPE_JPEG);
$attachment->fastUpdate([
'thumbnail_width' => $thumbW,
'thumbnail_height' => $thumbH,
'thumbnail_date' => \XF::$time
]);
file_put_contents($logFile, "Thumbnail generated at: " . $thumbnailPath . "\n", FILE_APPEND);
} else {
file_put_contents($logFile, "Thumbnail generation failed (GD/ImageMagick issue).\n", FILE_APPEND);
}
return $this->message([
'attachment_id' => $attachment->attachment_id,
'thumbnail' => true,
'html' => '[ATTACH type="thumb"]' . $attachment->attachment_id . '[/ATTACH]'
]);
}
}
editor.js
JavaScript:
!function($, window, document, _undefined) {
"use strict";
XF.EditorPasteHandler = XF.Element.newHandler({
options: {},
init: function() {
console.log('EditorPasteHandler initialized at ' + new Date().toISOString());
this.$target.on('paste', XF.proxy(this, 'onPaste'));
},
onPaste: function(e) {
console.log('Paste event fired at ' + new Date().toISOString());
var clipboardData = e.originalEvent.clipboardData || window.clipboardData;
if (!clipboardData || !clipboardData.items) {
console.log('No clipboard data available');
return;
}
var items = clipboardData.items;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') === 0) {
var blob = items[i].getAsFile();
if (blob) {
console.log('Image detected, size: ' + blob.size + ' bytes');
this.uploadImage(blob);
e.preventDefault();
break;
}
}
}
},
uploadImage: function(blob) {
var formData = new FormData();
formData.append('upload', blob);
XF.ajax('POST', XF.canonicalizeUrl('index.php?editor/paste'), formData,
XF.proxy(this, 'uploadSuccess'),
{ contentType: false, processData: false }
).fail(function(xhr) {
console.error('Upload failed: ' + (xhr.responseText || 'Unknown error'));
});
},
uploadSuccess: function(data) {
console.log('Upload success: ' + JSON.stringify(data));
if (data.html) {
console.log('Inserting BB code: ' + data.html);
var editor = this.$target.data('xf-editor');
if (editor) {
editor.insertContent(data.html);
} else {
console.error('Editor instance not found');
}
} else {
console.error('No HTML in response');
}
}
});
XF.Element.register('editor-paste-handler', 'XF.EditorPasteHandler');
}(jQuery, window, document);
Attachment.php
PHP:
namespace KiwiNail\Listener;
use XF\Attachment\Manipulator;
use XF\Entity\Attachment;
use XF\Pub\Controller\Attachment as AttachmentController;
class Attachment
{
public static function postUpload(Manipulator $manipulator, Attachment $attachment, $context)
{
if (strpos($attachment->getFile()->getType(), 'image/') === 0) {
$thumbW = 250;
$thumbH = 250;
if (!$attachment->hasThumbnail()) {
$image = \XF::app()->imageManager()->imageFromFile($attachment->getFile()->getPath());
if ($image) {
$image->resizeAndCrop($thumbW, $thumbH);
$image->save($attachment->getThumbnailPath());
$attachment->set('thumbnail_width', $thumbW);
$attachment->set('thumbnail_height', $thumbH);
$attachment->save();
}
}
}
}
public static function preInsert(AttachmentController $controller, &$output, &$insertFull)
{
$insertFull = false;
}
}
Addon.json
JSON:
{
"legacy_addon_id": "",
"addon_id": "KiwiNail/UploadImagePaste",
"title": "KiwiNail - Auto Thumbnail Generator",
"description": "Automatically generates thumbnails for images in posts, whether uploaded or pasted from the clipboard.",
"version_id": 1000010,
"version_string": "1.0.0",
"dev": "Osama Bin Laden",
"dev_url": "https://kiwifarms.st",
"faq_url": "",
"support_url": "",
"extra_urls": [],
"require": {
"XF": "2.3.3"
},
"icon": "",
"listeners": {
"XF\\Attachment\\Manipulator::postUpload": "KiwiNail\\Listener\\Attachment::postUpload",
"XF\\Pub\\Controller\\Attachment::preInsert": "KiwiNail\\Listener\\Attachment::preInsert"
},
"additional_files": [
"js/kiwinail/editor.js"
]
}
Attachments
Last edited: