initial cbz support
This commit is contained in:
parent
6947b726f0
commit
ca462d86f1
9 changed files with 224 additions and 0 deletions
78
ext/handle_cbz/comic.js
Normal file
78
ext/handle_cbz/comic.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
function Comic(root, comicURL) {
|
||||
let self = this;
|
||||
|
||||
this.root = document.getElementById(root);
|
||||
this.comicPages = [];
|
||||
this.comicPage = 0;
|
||||
this.comicZip = null;
|
||||
|
||||
this.setComic = function(zip) {
|
||||
let self = this;
|
||||
self.comicZip = zip;
|
||||
|
||||
// Shimmie-specific; nullify existing back / forward
|
||||
$("[rel='previous']").remove();
|
||||
$("[rel='next']").remove();
|
||||
|
||||
zip.forEach(function (relativePath, file){
|
||||
self.comicPages.push(relativePath);
|
||||
});
|
||||
self.comicPages.sort();
|
||||
for(let i=0; i<self.comicPages.length; i++) {
|
||||
let op = document.createElement("OPTION");
|
||||
op.value = i;
|
||||
op.innerText = (i+1) + " / " + self.comicPages.length + " - " + self.comicPages[i];
|
||||
document.getElementById("comicPageList").appendChild(op);
|
||||
}
|
||||
self.setPage(0);
|
||||
};
|
||||
|
||||
this.setPage = function(n) {
|
||||
self.comicPage = n;
|
||||
|
||||
self.comicZip.file(self.comicPages[n]).async("arraybuffer").then(function(arrayBufferView) {
|
||||
let blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
|
||||
let urlCreator = window.URL || window.webkitURL;
|
||||
document.getElementById("comicPage").src = urlCreator.createObjectURL( blob );
|
||||
});
|
||||
document.getElementById("comicPageList").value = self.comicPage;
|
||||
};
|
||||
|
||||
this.prev = function() {
|
||||
if(self.comicPage > 0) {
|
||||
self.setPage(self.comicPage-1);
|
||||
}
|
||||
};
|
||||
|
||||
this.next = function() {
|
||||
if(self.comicPage < self.comicPages.length) {
|
||||
self.setPage(self.comicPage+1);
|
||||
}
|
||||
};
|
||||
|
||||
this.onKeyUp = function(e) {
|
||||
if ($(e.target).is('input,textarea')) { return; }
|
||||
if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) { return; }
|
||||
if (e.keyCode === 37) {self.prev();}
|
||||
else if (e.keyCode === 39) {self.next();}
|
||||
};
|
||||
|
||||
this.onPageChanged = function(e) {
|
||||
self.setPage(parseInt(document.getElementById("comicPageList").value));
|
||||
};
|
||||
|
||||
JSZipUtils.getBinaryContent(comicURL, function(err, data) {
|
||||
if(err) {throw err;}
|
||||
JSZip.loadAsync(data).then(function (zip) {
|
||||
self.setComic(zip);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("keyup", this.onKeyUp);
|
||||
document.getElementById("comicNext").addEventListener("click", this.next);
|
||||
document.getElementById("comicPrev").addEventListener("click", this.prev);
|
||||
document.getElementById("comicPageList").addEventListener("change", this.onPageChanged);
|
||||
document.getElementById("comicPageList").addEventListener("keyup", function(e) {e.stopPropagation();});
|
||||
|
||||
return this;
|
||||
}
|
12
ext/handle_cbz/info.php
Normal file
12
ext/handle_cbz/info.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
class CBZFileHandlerInfo extends ExtensionInfo
|
||||
{
|
||||
public const KEY = "handle_cbz";
|
||||
|
||||
public $key = self::KEY;
|
||||
public $name = "Handle CBZ";
|
||||
public $url = self::SHIMMIE_URL;
|
||||
public $authors = self::SHISH_AUTHOR;
|
||||
public $description = "Handle CBZ Comic Archives.";
|
||||
}
|
1
ext/handle_cbz/jszip-utils-ie.min.js
vendored
Normal file
1
ext/handle_cbz/jszip-utils-ie.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!function i(o,a,y){function f(t,r){if(!a[t]){if(!o[t]){var n="function"==typeof require&&require;if(!r&&n)return n(t,!0);if(u)return u(t,!0);throw new Error("Cannot find module '"+t+"'")}var e=a[t]={exports:{}};o[t][0].call(e.exports,function(r){var n=o[t][1][r];return f(n||r)},e,e.exports,i,o,a,y)}return a[t].exports}for(var u="function"==typeof require&&require,r=0;r<y.length;r++)f(y[r]);return f}({1:[function(r,n,t){var e="undefined"!=typeof self?self:"undefined"!=typeof window?window:{};document.write("\x3c!-- IEBinaryToArray_ByteStr --\x3e\r\n<script type='text/vbscript'>\r\nFunction IEBinaryToArray_ByteStr(Binary)\r\n IEBinaryToArray_ByteStr = CStr(Binary)\r\nEnd Function\r\nFunction IEBinaryToArray_ByteStr_Last(Binary)\r\n Dim lastIndex\r\n lastIndex = LenB(Binary)\r\n if lastIndex mod 2 Then\r\n IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )\r\n Else\r\n IEBinaryToArray_ByteStr_Last = \"\"\r\n End If\r\nEnd Function\r\n<\/script>\r\n"),e.JSZipUtils._getBinaryFromXHR=function(r){for(var n=r.responseBody,t={},e=0;e<256;e++)for(var i=0;i<256;i++)t[String.fromCharCode(e+(i<<8))]=String.fromCharCode(e)+String.fromCharCode(i);var o=IEBinaryToArray_ByteStr(n),a=IEBinaryToArray_ByteStr_Last(n);return o.replace(/[\s\S]/g,function(r){return t[r]})+a}},{}]},{},[1]);
|
1
ext/handle_cbz/jszip-utils.min.js
vendored
Normal file
1
ext/handle_cbz/jszip-utils.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){return function o(i,f,u){function s(n,e){if(!f[n]){if(!i[n]){var t="function"==typeof require&&require;if(!e&&t)return t(n,!0);if(a)return a(n,!0);throw new Error("Cannot find module '"+n+"'")}var r=f[n]={exports:{}};i[n][0].call(r.exports,function(e){var t=i[n][1][e];return s(t||e)},r,r.exports,o,i,f,u)}return f[n].exports}for(var a="function"==typeof require&&require,e=0;e<u.length;e++)s(u[e]);return s}({1:[function(e,t,n){"use strict";var u={};function r(){try{return new window.XMLHttpRequest}catch(e){}}u._getBinaryFromXHR=function(e){return e.response||e.responseText};var s="undefined"!=typeof window&&window.ActiveXObject?function(){return r()||function(){try{return new window.ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}()}:r;u.getBinaryContent=function(t,n){var e,r,o,i;"function"==typeof(n=n||{})?(i=n,n={}):"function"==typeof n.callback&&(i=n.callback),i||"undefined"==typeof Promise?(r=function(e){i(null,e)},o=function(e){i(e,null)}):e=new Promise(function(e,t){r=e,o=t});try{var f=s();f.open("GET",t,!0),"responseType"in f&&(f.responseType="arraybuffer"),f.overrideMimeType&&f.overrideMimeType("text/plain; charset=x-user-defined"),f.onreadystatechange=function(e){if(4===f.readyState)if(200===f.status||0===f.status)try{r(u._getBinaryFromXHR(f))}catch(e){o(new Error(e))}else o(new Error("Ajax error for "+t+" : "+this.status+" "+this.statusText))},n.progress&&(f.onprogress=function(e){n.progress({path:t,originalEvent:e,percent:e.loaded/e.total*100,loaded:e.loaded,total:e.total})}),f.send()}catch(e){o(new Error(e),null)}return e},t.exports=u},{}]},{},[1])(1)});
|
13
ext/handle_cbz/jszip.min.js
vendored
Normal file
13
ext/handle_cbz/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
66
ext/handle_cbz/main.php
Normal file
66
ext/handle_cbz/main.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
class CBZFileHandler extends DataHandlerExtension
|
||||
{
|
||||
public $SUPPORTED_EXT = ["cbz"];
|
||||
|
||||
protected function media_check_properties(MediaCheckPropertiesEvent $event): void
|
||||
{
|
||||
$event->image->lossless = false;
|
||||
$event->image->video = false;
|
||||
$event->image->audio = false;
|
||||
$event->image->image = false;
|
||||
|
||||
$tmp = $this->get_representative_image($event->file_name);
|
||||
$info = getimagesize($tmp);
|
||||
if ($info) {
|
||||
$event->image->width = $info[0];
|
||||
$event->image->height = $info[1];
|
||||
}
|
||||
unlink($tmp);
|
||||
}
|
||||
|
||||
protected function create_thumb(string $hash, string $type): bool
|
||||
{
|
||||
$cover = $this->get_representative_image(warehouse_path(Image::IMAGE_DIR, $hash));
|
||||
create_scaled_image(
|
||||
$cover,
|
||||
warehouse_path(Image::THUMBNAIL_DIR, $hash),
|
||||
get_thumbnail_max_size_scaled(),
|
||||
get_extension(getMimeType($cover)),
|
||||
null
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function check_contents(string $tmpname): bool
|
||||
{
|
||||
$fp = fopen($tmpname, "r");
|
||||
$head = fread($fp, 4);
|
||||
fclose($fp);
|
||||
return $head == "PK\x03\x04";
|
||||
}
|
||||
|
||||
private function get_representative_image(string $archive): string
|
||||
{
|
||||
$out = "data/comic-cover-FIXME.jpg"; // TODO: random
|
||||
|
||||
$za = new ZipArchive();
|
||||
$za->open($archive);
|
||||
$names = [];
|
||||
for ($i=0; $i<$za->numFiles;$i++) {
|
||||
$file = $za->statIndex($i);
|
||||
$names[] = $file['name'];
|
||||
}
|
||||
sort($names);
|
||||
$cover = $names[0];
|
||||
foreach ($names as $name) {
|
||||
if (strpos(strtolower($name), "cover") !== false) {
|
||||
$cover = $name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
file_put_contents($out, $za->getFromName($cover));
|
||||
return $out;
|
||||
}
|
||||
}
|
BIN
ext/handle_cbz/spinner.gif
Normal file
BIN
ext/handle_cbz/spinner.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
26
ext/handle_cbz/style.css
Normal file
26
ext/handle_cbz/style.css
Normal file
|
@ -0,0 +1,26 @@
|
|||
#comicMain {
|
||||
background: black;
|
||||
color: white;
|
||||
font-size: 3em;
|
||||
}
|
||||
#comicPageList {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
#comicView {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
}
|
||||
#comicView #comicPage {
|
||||
flex: 10 auto;
|
||||
}
|
||||
#comicView #comicPrev,
|
||||
#comicView #comicNext {
|
||||
flex: 1 auto;
|
||||
padding-top: 45%;
|
||||
}
|
||||
#comicView .comicPager {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
margin: auto;
|
||||
}
|
27
ext/handle_cbz/theme.php
Normal file
27
ext/handle_cbz/theme.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
class CBZFileHandlerTheme extends Themelet
|
||||
{
|
||||
public function display_image(Page $page, Image $image)
|
||||
{
|
||||
$data_href = get_base_href();
|
||||
$ilink = $image->get_image_link();
|
||||
$html = "
|
||||
<div id='comicMain'>
|
||||
<div class='comicPager'>
|
||||
<select id='comicPageList'></select>
|
||||
</div>
|
||||
<div id='comicView'>
|
||||
<a id='comicPrev'><span><</span></a>
|
||||
<img id='comicPage' src='{$data_href}/ext/handle_cbz/spinner.gif' />
|
||||
<a id='comicNext'><span>></span></a>
|
||||
</div>
|
||||
</div>
|
||||
<script src='{$data_href}/ext/handle_cbz/jszip-utils.min.js'></script>
|
||||
<script src='{$data_href}/ext/handle_cbz/jszip.min.js'></script>
|
||||
<script src='{$data_href}/ext/handle_cbz/comic.js'></script>
|
||||
<script>window.comic = new Comic('comicMain', '$ilink');</script>
|
||||
";
|
||||
$page->add_block(new Block("Comic", $html, "main", 10, "comicBlock"));
|
||||
}
|
||||
}
|
Reference in a new issue