mirror of
https://github.com/vichan-devel/vichan.git
synced 2025-01-19 09:27:24 +01:00
This commit is contained in:
commit
6f195a033c
@ -755,6 +755,13 @@
|
|||||||
// Display the file's original filename.
|
// Display the file's original filename.
|
||||||
$config['show_filename'] = true;
|
$config['show_filename'] = true;
|
||||||
|
|
||||||
|
// WebM Settings
|
||||||
|
$config['webm']['use_ffmpeg'] = false;
|
||||||
|
$config['webm']['allow_audio'] = false;
|
||||||
|
$config['webm']['max_length'] = 120;
|
||||||
|
$config['webm']['ffmpeg_path'] = 'ffmpeg';
|
||||||
|
$config['webm']['ffprobe_path'] = 'ffprobe';
|
||||||
|
|
||||||
// Display image identification links for ImgOps, regex.info/exif, Google Images and iqdb.
|
// Display image identification links for ImgOps, regex.info/exif, Google Images and iqdb.
|
||||||
$config['image_identification'] = false;
|
$config['image_identification'] = false;
|
||||||
// Which of the identification links to display. Only works if $config['image_identification'] is true.
|
// Which of the identification links to display. Only works if $config['image_identification'] is true.
|
||||||
@ -764,6 +771,9 @@
|
|||||||
// Anime/manga search engine.
|
// Anime/manga search engine.
|
||||||
$config['image_identification_iqdb'] = false;
|
$config['image_identification_iqdb'] = false;
|
||||||
|
|
||||||
|
// Set this to true if you're using a BSD
|
||||||
|
$config['bsd_md5'] = false;
|
||||||
|
|
||||||
// Number of posts in a "View Last X Posts" page
|
// Number of posts in a "View Last X Posts" page
|
||||||
$config['noko50_count'] = 50;
|
$config['noko50_count'] = 50;
|
||||||
// Number of posts a thread needs before it gets a "View Last X Posts" page.
|
// Number of posts a thread needs before it gets a "View Last X Posts" page.
|
||||||
@ -1036,6 +1046,10 @@
|
|||||||
$config['error']['unknownext'] = _('Unknown file extension.');
|
$config['error']['unknownext'] = _('Unknown file extension.');
|
||||||
$config['error']['filesize'] = _('Maximum file size: %maxsz% bytes<br>Your file\'s size: %filesz% bytes');
|
$config['error']['filesize'] = _('Maximum file size: %maxsz% bytes<br>Your file\'s size: %filesz% bytes');
|
||||||
$config['error']['maxsize'] = _('The file was too big.');
|
$config['error']['maxsize'] = _('The file was too big.');
|
||||||
|
$config['error']['webmerror'] = _('There was a problem processing your webm.');
|
||||||
|
$config['error']['invalidwebm'] = _('Invalid webm uploaded.');
|
||||||
|
$config['error']['webmhasaudio'] = _('The uploaded webm contains an audio or another type of additional stream.');
|
||||||
|
$config['error']['webmtoolong'] = _('The uploaded webm is longer than ' . $config['webm']['max_length'] . ' seconds.');
|
||||||
$config['error']['fileexists'] = _('That file <a href="%s">already exists</a>!');
|
$config['error']['fileexists'] = _('That file <a href="%s">already exists</a>!');
|
||||||
$config['error']['fileexistsinthread'] = _('That file <a href="%s">already exists</a> in this thread!');
|
$config['error']['fileexistsinthread'] = _('That file <a href="%s">already exists</a> in this thread!');
|
||||||
$config['error']['delete_too_soon'] = _('You\'ll have to wait another %s before deleting that.');
|
$config['error']['delete_too_soon'] = _('You\'ll have to wait another %s before deleting that.');
|
||||||
@ -1043,6 +1057,7 @@
|
|||||||
$config['error']['invalid_embed'] = _('Couldn\'t make sense of the URL of the video you tried to embed.');
|
$config['error']['invalid_embed'] = _('Couldn\'t make sense of the URL of the video you tried to embed.');
|
||||||
$config['error']['captcha'] = _('You seem to have mistyped the verification.');
|
$config['error']['captcha'] = _('You seem to have mistyped the verification.');
|
||||||
|
|
||||||
|
|
||||||
// Moderator errors
|
// Moderator errors
|
||||||
$config['error']['toomanyunban'] = _('You are only allowed to unban %s users at a time. You tried to unban %u users.');
|
$config['error']['toomanyunban'] = _('You are only allowed to unban %s users at a time. You tried to unban %u users.');
|
||||||
$config['error']['invalid'] = _('Invalid username and/or password.');
|
$config['error']['invalid'] = _('Invalid username and/or password.');
|
||||||
|
@ -20,6 +20,16 @@ Add these lines to inc/instance-config.php:
|
|||||||
$config['additional_javascript'][] = 'js/webm-settings.js';
|
$config['additional_javascript'][] = 'js/webm-settings.js';
|
||||||
$config['additional_javascript'][] = 'js/expand-video.js';
|
$config['additional_javascript'][] = 'js/expand-video.js';
|
||||||
|
|
||||||
|
If you have an [FFmpeg](https://www.ffmpeg.org/) binary on your server and you wish to generate real thumbnails (the webm thumbnails created with the original implementation reportedly cause users' browsers to crash), add the following to inc/instance-config.php as well:
|
||||||
|
|
||||||
|
$config['webm']['use_ffmpeg'] = true;
|
||||||
|
|
||||||
|
// If your ffmpeg binary isn't in your path you need to set these options
|
||||||
|
// as well.
|
||||||
|
|
||||||
|
$config['webm']['ffmpeg_path'] = '/path/to/ffmeg';
|
||||||
|
$config['webm']['ffprobe_path'] = '/path/to/ffprobe';
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
62
inc/lib/webm/ffmpeg.php
Normal file
62
inc/lib/webm/ffmpeg.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* ffmpeg.php
|
||||||
|
* A barebones ffmpeg based webm implementation for vichan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function get_webm_info($filename) {
|
||||||
|
global $board, $config;
|
||||||
|
|
||||||
|
$filename = escapeshellarg($filename);
|
||||||
|
$ffprobe = $config['webm']['ffprobe_path'];
|
||||||
|
$ffprobe_out = array();
|
||||||
|
$webminfo = array();
|
||||||
|
|
||||||
|
exec("$ffprobe -v quiet -print_format json -show_format -show_streams $filename", $ffprobe_out);
|
||||||
|
$ffprobe_out = json_decode(implode("\n", $ffprobe_out), 1);
|
||||||
|
$webminfo['error'] = is_valid_webm($ffprobe_out);
|
||||||
|
|
||||||
|
if(empty($webminfo['error'])) {
|
||||||
|
$webminfo['width'] = $ffprobe_out['streams'][0]['width'];
|
||||||
|
$webminfo['height'] = $ffprobe_out['streams'][0]['height'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $webminfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_valid_webm($ffprobe_out) {
|
||||||
|
global $board, $config;
|
||||||
|
|
||||||
|
if (empty($ffprobe_out))
|
||||||
|
return array('code' => 1, 'msg' => $config['error']['genwebmerror']);
|
||||||
|
|
||||||
|
if ($ffprobe_out['format']['format_name'] != 'matroska,webm')
|
||||||
|
return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
|
||||||
|
|
||||||
|
if ((count($ffprobe_out['streams']) > 1) && (!$config['webm']['allow_audio']))
|
||||||
|
return array('code' => 3, 'msg' => $config['error']['webmhasaudio']);
|
||||||
|
|
||||||
|
if ($ffprobe_out['streams'][0]['codec_name'] != 'vp8')
|
||||||
|
return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
|
||||||
|
|
||||||
|
if (empty($ffprobe_out['streams'][0]['width']) || (empty($ffprobe_out['streams'][0]['height'])))
|
||||||
|
return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
|
||||||
|
|
||||||
|
if ($ffprobe_out['format']['duration'] > $config['webm']['max_length'])
|
||||||
|
return array('code' => 4, 'msg' => $config['error']['webmtoolong']);
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_webm_thumbnail($filename, $thumbnail, $width, $height) {
|
||||||
|
global $board, $config;
|
||||||
|
|
||||||
|
$filename = escapeshellarg($filename);
|
||||||
|
$thumbnail = escapeshellarg($thumbnail); // Should be safe by default but you
|
||||||
|
// can never be too safe.
|
||||||
|
|
||||||
|
$ffmpeg = $config['webm']['ffmpeg_path'];
|
||||||
|
$ffmpeg_out = array();
|
||||||
|
|
||||||
|
exec("$ffmpeg -i $filename -v quiet -ss 00:00:00 -an -vframes 1 -f mjpeg -vf scale=$width:$height $thumbnail 2>&1");
|
||||||
|
|
||||||
|
return count($ffmpeg_out);
|
||||||
|
}
|
@ -6,6 +6,34 @@ function postHandler($post) {
|
|||||||
global $board, $config;
|
global $board, $config;
|
||||||
|
|
||||||
if ($post->has_file) foreach ($post->files as &$file) if ($file->extension == 'webm') {
|
if ($post->has_file) foreach ($post->files as &$file) if ($file->extension == 'webm') {
|
||||||
|
if ($config['webm']['use_ffmpeg']) {
|
||||||
|
require_once dirname(__FILE__) . '/ffmpeg.php';
|
||||||
|
$webminfo = get_webm_info($file->file_path);
|
||||||
|
|
||||||
|
if (empty($webminfo['error'])) {
|
||||||
|
$file->width = $webminfo['width'];
|
||||||
|
$file->height = $webminfo['height'];
|
||||||
|
|
||||||
|
if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
|
||||||
|
$file = webm_set_spoiler($file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$file = set_thumbnail_dimensions($post, $file);
|
||||||
|
$tn_path = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.jpg';
|
||||||
|
|
||||||
|
if(empty(make_webm_thumbnail($file->file_path, $tn_path, $file->thumbwidth, $file->thumbheight))) {
|
||||||
|
$file->thumb = $file->file_id . '.jpg';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$file->thumb = 'file';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $webminfo['error']['msg'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
require_once dirname(__FILE__) . '/videodata.php';
|
require_once dirname(__FILE__) . '/videodata.php';
|
||||||
$videoDetails = videoData($file->file_path);
|
$videoDetails = videoData($file->file_path);
|
||||||
if (!isset($videoDetails['container']) || $videoDetails['container'] != 'webm') return "not a WebM file";
|
if (!isset($videoDetails['container']) || $videoDetails['container'] != 'webm') return "not a WebM file";
|
||||||
@ -14,10 +42,7 @@ function postHandler($post) {
|
|||||||
$thumbName = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.webm';
|
$thumbName = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.webm';
|
||||||
if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
|
if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
|
||||||
// Use spoiler thumbnail
|
// Use spoiler thumbnail
|
||||||
$file->thumb = 'spoiler';
|
$file = webm_set_spoiler($file);
|
||||||
$size = @getimagesize($config['spoiler_image']);
|
|
||||||
$file->thumbwidth = $size[0];
|
|
||||||
$file->thumbheight = $size[1];
|
|
||||||
} elseif (isset($videoDetails['frame']) && $thumbFile = fopen($thumbName, 'wb')) {
|
} elseif (isset($videoDetails['frame']) && $thumbFile = fopen($thumbName, 'wb')) {
|
||||||
// Use single frame from video as pseudo-thumbnail
|
// Use single frame from video as pseudo-thumbnail
|
||||||
fwrite($thumbFile, $videoDetails['frame']);
|
fwrite($thumbFile, $videoDetails['frame']);
|
||||||
@ -33,17 +58,40 @@ function postHandler($post) {
|
|||||||
if (isset($videoDetails['width']) && isset($videoDetails['height'])) {
|
if (isset($videoDetails['width']) && isset($videoDetails['height'])) {
|
||||||
$file->width = $videoDetails['width'];
|
$file->width = $videoDetails['width'];
|
||||||
$file->height = $videoDetails['height'];
|
$file->height = $videoDetails['height'];
|
||||||
|
|
||||||
if ($file->thumb != 'file' && $file->thumb != 'spoiler') {
|
if ($file->thumb != 'file' && $file->thumb != 'spoiler') {
|
||||||
$thumbMaxWidth = $post->op ? $config['thumb_op_width'] : $config['thumb_width'];
|
$file = set_thumbnail_dimensions($post, $file);
|
||||||
$thumbMaxHeight = $post->op ? $config['thumb_op_height'] : $config['thumb_height'];
|
}
|
||||||
if ($videoDetails['width'] > $thumbMaxWidth || $videoDetails['height'] > $thumbMaxHeight) {
|
}
|
||||||
$file->thumbwidth = min($thumbMaxWidth, intval(round($videoDetails['width'] * $thumbMaxHeight / $videoDetails['height'])));
|
}
|
||||||
$file->thumbheight = min($thumbMaxHeight, intval(round($videoDetails['height'] * $thumbMaxWidth / $videoDetails['width'])));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_thumbnail_dimensions($post,$file) {
|
||||||
|
global $board, $config;
|
||||||
|
|
||||||
|
$tn_dimensions = array();
|
||||||
|
$tn_maxw = $post->op ? $config['thumb_op_width'] : $config['thumb_width'];
|
||||||
|
$tn_maxh = $post->op ? $config['thumb_op_height'] : $config['thumb_height'];
|
||||||
|
|
||||||
|
if ($file->width > $tn_maxw || $file->height > $tn_maxh) {
|
||||||
|
$file->thumbwidth = min($tn_maxw, intval(round($file->width * $tn_maxh / $file->height)));
|
||||||
|
$file->thumbheight = min($tn_maxh, intval(round($file->height * $tn_maxw / $file->width)));
|
||||||
} else {
|
} else {
|
||||||
$file->thumbwidth = $videoDetails['width'];
|
$file->thumbwidth = $file->width;
|
||||||
$file->thumbheight = $videoDetails['height'];
|
$file->thumbheight = $file->height;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function webm_set_spoiler($file) {
|
||||||
|
global $board, $config;
|
||||||
|
|
||||||
|
$file->thumb = 'spoiler';
|
||||||
|
$size = @getimagesize($config['spoiler_image']);
|
||||||
|
$file->thumbwidth = $size[0];
|
||||||
|
$file->thumbheight = $size[1];
|
||||||
|
|
||||||
|
return $file;
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,9 @@ if (active_page == 'catalog') $(function(){
|
|||||||
|
|
||||||
$("#image_size").change(function(){
|
$("#image_size").change(function(){
|
||||||
var value = this.value, old;
|
var value = this.value, old;
|
||||||
if (value == "small") {
|
$(".grid-li").removeClass("grid-size-vsmall");
|
||||||
old = "large";
|
$(".grid-li").removeClass("grid-size-small");
|
||||||
} else {
|
$(".grid-li").removeClass("grid-size-large");
|
||||||
old = "small";
|
|
||||||
}
|
|
||||||
$(".grid-li").removeClass("grid-size-"+old);
|
|
||||||
$(".grid-li").addClass("grid-size-"+value);
|
$(".grid-li").addClass("grid-size-"+value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -218,7 +218,8 @@ function setupVideosIn(element) {
|
|||||||
|
|
||||||
onready(function(){
|
onready(function(){
|
||||||
// Insert menu from settings.js
|
// Insert menu from settings.js
|
||||||
if (typeof settingsMenu != "undefined") document.body.insertBefore(settingsMenu, document.getElementsByTagName("hr")[0]);
|
if (typeof settingsMenu != "undefined" && typeof Options == "undefined")
|
||||||
|
document.body.insertBefore(settingsMenu, document.getElementsByTagName("hr")[0]);
|
||||||
|
|
||||||
// Setup Javascript events for videos in document now
|
// Setup Javascript events for videos in document now
|
||||||
setupVideosIn(document);
|
setupVideosIn(document);
|
||||||
|
126
js/options.js
Normal file
126
js/options.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* options.js - allow users choose board options as they wish
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* $config['additional_javascript'][] = 'js/jquery.min.js';
|
||||||
|
* $config['additional_javascript'][] = 'js/options.js';
|
||||||
|
*/
|
||||||
|
|
||||||
|
+function(){
|
||||||
|
|
||||||
|
var options_button, options_handler, options_background, options_div
|
||||||
|
, options_close, options_tablist, options_tabs, options_current_tab;
|
||||||
|
|
||||||
|
var Options = {};
|
||||||
|
window.Options = Options;
|
||||||
|
|
||||||
|
var first_tab = function() {
|
||||||
|
for (var i in options_tabs) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.show = function() {
|
||||||
|
if (!options_current_tab) {
|
||||||
|
Options.select_tab(first_tab(), true);
|
||||||
|
}
|
||||||
|
options_handler.fadeIn();
|
||||||
|
};
|
||||||
|
Options.hide = function() {
|
||||||
|
options_handler.fadeOut();
|
||||||
|
};
|
||||||
|
|
||||||
|
options_tabs = {};
|
||||||
|
|
||||||
|
Options.add_tab = function(id, icon, name, content) {
|
||||||
|
var tab = {};
|
||||||
|
|
||||||
|
if (typeof content == "string") {
|
||||||
|
content = $("<div>"+content+"</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.id = id;
|
||||||
|
tab.name = name;
|
||||||
|
tab.icon = $("<div class='options_tab_icon'><i class='fa fa-"+icon+"'></i><div>"+name+"</div></div>");
|
||||||
|
tab.content = $("<div class='options_tab'></div>").css("display", "none");
|
||||||
|
|
||||||
|
tab.content.appendTo(options_div);
|
||||||
|
|
||||||
|
tab.icon.on("click", function() {
|
||||||
|
Options.select_tab(id);
|
||||||
|
}).appendTo(options_tablist);
|
||||||
|
|
||||||
|
$("<h2>"+name+"</h2>").appendTo(tab.content);
|
||||||
|
|
||||||
|
if (content) {
|
||||||
|
content.appendTo(tab.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
options_tabs[id] = tab;
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.get_tab = function(id) {
|
||||||
|
return options_tabs[id];
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.extend_tab = function(id, content) {
|
||||||
|
if (typeof content == "string") {
|
||||||
|
content = $("<div>"+content+"</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
content.appendTo(options_tabs[id].content);
|
||||||
|
|
||||||
|
return options_tabs[id];
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.select_tab = function(id, quick) {
|
||||||
|
if (options_current_tab) {
|
||||||
|
if (options_current_tab.id == id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
options_current_tab.content.fadeOut();
|
||||||
|
options_current_tab.icon.removeClass("active");
|
||||||
|
}
|
||||||
|
var tab = options_tabs[id];
|
||||||
|
options_current_tab = tab;
|
||||||
|
options_current_tab.icon.addClass("active");
|
||||||
|
tab.content[quick? "show" : "fadeIn"]();
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
};
|
||||||
|
|
||||||
|
options_handler = $("<div id='options_handler'></div>").css("display", "none");
|
||||||
|
options_background = $("<div id='options_background'></div>").on("click", Options.hide).appendTo(options_handler);
|
||||||
|
options_div = $("<div id='options_div'></div>").appendTo(options_handler);
|
||||||
|
options_close = $("<a id='options_close' href='javascript:void(0)'><i class='fa fa-times'></i></div>")
|
||||||
|
.on("click", Options.hide).appendTo(options_div);
|
||||||
|
options_tablist = $("<div id='options_tablist'></div>").appendTo(options_div);
|
||||||
|
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
options_button = $("<a href='javascript:void(0)' title='"+_("Options")+"'>["+_("Options")+"]</a>").css("float", "right");
|
||||||
|
|
||||||
|
if ($(".boardlist.compact-boardlist").length) {
|
||||||
|
options_button.addClass("cb-item cb-fa").html("<i class='fa fa-gear'></i>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($(".boardlist:first").length) {
|
||||||
|
options_button.appendTo($(".boardlist:first"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
options_button.prependTo($(document.body));
|
||||||
|
}
|
||||||
|
|
||||||
|
options_button.on("click", Options.show);
|
||||||
|
|
||||||
|
options_handler.appendTo($(document.body));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}();
|
44
js/options/general.js
Normal file
44
js/options/general.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* options/general.js - general settings tab for options panel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* $config['additional_javascript'][] = 'js/jquery.min.js';
|
||||||
|
* $config['additional_javascript'][] = 'js/options.js';
|
||||||
|
* $config['additional_javascript'][] = 'js/style-select.js';
|
||||||
|
* $config['additional_javascript'][] = 'js/options/general.js';
|
||||||
|
*/
|
||||||
|
|
||||||
|
+function(){
|
||||||
|
|
||||||
|
var tab = Options.add_tab("general", "home", _("General"));
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
var stor = $("<div>"+_("Storage: ")+"</div>");
|
||||||
|
stor.appendTo(tab.content);
|
||||||
|
|
||||||
|
$("<button>"+_("Export")+"</button>").appendTo(stor).on("click", function() {
|
||||||
|
var str = JSON.stringify(localStorage);
|
||||||
|
|
||||||
|
$(".output").remove();
|
||||||
|
$("<input type='text' class='output'>").appendTo(stor).val(str);
|
||||||
|
});
|
||||||
|
$("<button>"+_("Import")+"</button>").appendTo(stor).on("click", function() {
|
||||||
|
var str = prompt(_("Paste your storage data"));
|
||||||
|
if (!str) return false;
|
||||||
|
var obj = JSON.parse(str);
|
||||||
|
if (!obj) return false;
|
||||||
|
|
||||||
|
localStorage.clear();
|
||||||
|
for (var i in obj) {
|
||||||
|
localStorage[i] = obj[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
document.location.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#style-select").detach().css({float:"none","margin-bottom":0}).appendTo(tab.content);
|
||||||
|
});
|
||||||
|
|
||||||
|
}();
|
@ -107,6 +107,7 @@ $(function(){
|
|||||||
var list = $("<div class='boardlist top cb-menu watch-menu'></div>");
|
var list = $("<div class='boardlist top cb-menu watch-menu'></div>");
|
||||||
list.attr("data-board", board);
|
list.attr("data-board", board);
|
||||||
|
|
||||||
|
if (storage()[board] && storage()[board].threads)
|
||||||
for (var tid in storage()[board].threads) {
|
for (var tid in storage()[board].threads) {
|
||||||
var newposts = "(0)";
|
var newposts = "(0)";
|
||||||
if (status && status[board] && status[board].threads && status[board].threads[tid]) {
|
if (status && status[board] && status[board].threads && status[board].threads[tid]) {
|
||||||
|
@ -36,15 +36,25 @@ function changeSetting(name, value) {
|
|||||||
|
|
||||||
// Create settings menu
|
// Create settings menu
|
||||||
var settingsMenu = document.createElement("div");
|
var settingsMenu = document.createElement("div");
|
||||||
|
var prefix = "", suffix = "", style = "";
|
||||||
|
if (window.Options) {
|
||||||
|
var tab = Options.add_tab("webm", "video-camera", _("WebM"));
|
||||||
|
$(settingsMenu).appendTo(tab.content);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prefix = '<a class="unimportant" href="javascript:void(0)">'+_('WebM Settings')+'</a>';
|
||||||
settingsMenu.style.textAlign = "right";
|
settingsMenu.style.textAlign = "right";
|
||||||
settingsMenu.style.background = "inherit";
|
settingsMenu.style.background = "inherit";
|
||||||
|
suffix = '</div>';
|
||||||
|
style = 'display: none; text-align: left; position: absolute; right: 1em; margin-left: -999em; margin-top: -1px; padding-top: 1px; background: inherit;';
|
||||||
|
}
|
||||||
|
|
||||||
settingsMenu.innerHTML = '<a class="unimportant" href="javascript:void(0)">'+_('WebM Settings')+'</a>'
|
settingsMenu.innerHTML = prefix
|
||||||
+ '<div style="display: none; text-align: left; position: absolute; right: 1em; margin-left: -999em; margin-top: -1px; padding-top: 1px; background: inherit;">'
|
+ '<div style="'+style+'">'
|
||||||
+ '<label><input type="checkbox" name="videoexpand">'+_('Expand videos inline')+'</label><br>'
|
+ '<label><input type="checkbox" name="videoexpand">'+_('Expand videos inline')+'</label><br>'
|
||||||
+ '<label><input type="checkbox" name="videohover">'+_('Play videos on hover')+'</label><br>'
|
+ '<label><input type="checkbox" name="videohover">'+_('Play videos on hover')+'</label><br>'
|
||||||
+ '<label><input type="range" name="videovolume" min="0" max="1" step="0.01" style="width: 4em; height: 1ex; vertical-align: middle; margin: 0px;">'+_('Default volume')+'</label><br>'
|
+ '<label><input type="range" name="videovolume" min="0" max="1" step="0.01" style="width: 4em; height: 1ex; vertical-align: middle; margin: 0px;">'+_('Default volume')+'</label><br>'
|
||||||
+ '</div>';
|
+ suffix;
|
||||||
|
|
||||||
function refreshSettings() {
|
function refreshSettings() {
|
||||||
var settingsItems = settingsMenu.getElementsByTagName("input");
|
var settingsItems = settingsMenu.getElementsByTagName("input");
|
||||||
@ -74,7 +84,7 @@ for (var i = 0; i < settingsItems.length; i++) {
|
|||||||
setupControl(settingsItems[i]);
|
setupControl(settingsItems[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingsMenu.addEventListener) {
|
if (settingsMenu.addEventListener && !window.Options) {
|
||||||
settingsMenu.addEventListener("mouseover", function(e) {
|
settingsMenu.addEventListener("mouseover", function(e) {
|
||||||
refreshSettings();
|
refreshSettings();
|
||||||
settingsMenu.getElementsByTagName("a")[0].style.fontWeight = "bold";
|
settingsMenu.getElementsByTagName("a")[0].style.fontWeight = "bold";
|
||||||
|
5
post.php
5
post.php
@ -571,7 +571,9 @@ if (isset($_POST['delete'])) {
|
|||||||
error($config['error']['nomove']);
|
error($config['error']['nomove']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($output = shell_exec_error("cat $filenames | md5sum")) {
|
$md5cmd = $config['bsd_md5'] ? 'md5 -r' : 'md5sum';
|
||||||
|
|
||||||
|
if ($output = shell_exec_error("cat $filenames | $md5cmd")) {
|
||||||
$explodedvar = explode(' ', $output);
|
$explodedvar = explode(' ', $output);
|
||||||
$hash = $explodedvar[0];
|
$hash = $explodedvar[0];
|
||||||
$post['filehash'] = $hash;
|
$post['filehash'] = $hash;
|
||||||
@ -930,4 +932,3 @@ if (isset($_POST['delete'])) {
|
|||||||
error($config['error']['nopost']);
|
error($config['error']['nopost']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,6 +539,17 @@ pre {
|
|||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-catalog div.grid-size-vsmall img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-catalog div.grid-size-vsmall {
|
||||||
|
width: 100px;
|
||||||
|
max-width: 100px;
|
||||||
|
max-height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
.theme-catalog div.grid-size-small {
|
.theme-catalog div.grid-size-small {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
@ -628,12 +639,6 @@ pre {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Containerchan */
|
|
||||||
div.post video.post-image {
|
|
||||||
padding: 0;
|
|
||||||
margin: 5px 25px 5px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* live-index.js */
|
/* live-index.js */
|
||||||
.new-posts {
|
.new-posts {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
@ -642,3 +647,76 @@ pre {
|
|||||||
.new-threads {
|
.new-threads {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* options.js */
|
||||||
|
#options_handler {
|
||||||
|
position: fixed;
|
||||||
|
top: 0px; left: 0px; right: 0px; bottom: 0px;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 9900;
|
||||||
|
}
|
||||||
|
#options_background {
|
||||||
|
background: black;
|
||||||
|
opacity: 0.5;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px; left: 0px; right: 0px; bottom: 0px;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
#options_div {
|
||||||
|
background-color: #d6daf0;
|
||||||
|
border: 1px solid black;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 600px;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
#options_close {
|
||||||
|
top: 0px; right: 0px;
|
||||||
|
position: absolute;
|
||||||
|
margin-right: 3px;
|
||||||
|
font-size: 20px; z-index: 100;
|
||||||
|
}
|
||||||
|
#options_tablist {
|
||||||
|
padding: 0px 5px;
|
||||||
|
left: 0px;
|
||||||
|
width: 70px;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid black;
|
||||||
|
}
|
||||||
|
.options_tab_icon {
|
||||||
|
padding: 5px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.options_tab_icon.active {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.options_tab_icon i {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.options_tab_icon div {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.options_tab {
|
||||||
|
padding: 10px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px; bottom: 0px;
|
||||||
|
left: 81px; right: 0px;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.options_tab h2 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-style #options_div {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
<span>{% trans 'Image size' %}: </span>
|
<span>{% trans 'Image size' %}: </span>
|
||||||
<select id="image_size" style="display: inline-block">
|
<select id="image_size" style="display: inline-block">
|
||||||
|
<option value="vsmall">{% trans 'Very small' %}</option>
|
||||||
<option selected value="small">{% trans 'Small' %}</option>
|
<option selected value="small">{% trans 'Small' %}</option>
|
||||||
<option value="large">{% trans 'Large' %}</option>
|
<option value="large">{% trans 'Large' %}</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -55,10 +55,29 @@
|
|||||||
|
|
||||||
if (isset($post['files'])) {
|
if (isset($post['files'])) {
|
||||||
$files = json_decode($post['files']);
|
$files = json_decode($post['files']);
|
||||||
if ($files[0]->file == 'deleted') continue;
|
|
||||||
$post['file'] = $config['uri_thumb'] . $files[0]->thumb;
|
if ($files[0]->file == 'deleted') {
|
||||||
|
if (count($files) > 1) {
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if (($file == $files[0]) || ($file->file == 'deleted')) continue;
|
||||||
|
$post['file'] = $config['uri_thumb'] . $file->thumb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($post['file'])) $post['file'] = $config['image_deleted'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$post['file'] = $config['image_deleted'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if($files[0]->thumb == 'spoiler') {
|
||||||
|
$post['file'] = '/' . $config['spoiler_image'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$post['file'] = $config['uri_thumb'] . $files[0]->thumb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($post['image_count'])) $post['image_count'] = 0;
|
||||||
$recent_posts[] = $post;
|
$recent_posts[] = $post;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +54,27 @@
|
|||||||
|
|
||||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||||
openBoard($post['board']);
|
openBoard($post['board']);
|
||||||
|
|
||||||
if (isset($post['files']))
|
if (isset($post['files']))
|
||||||
$files = json_decode($post['files']);
|
$files = json_decode($post['files']);
|
||||||
|
|
||||||
if ($files[0]->file == 'deleted') continue;
|
if ($files[0]->file == 'deleted') continue;
|
||||||
|
|
||||||
// board settings won't be available in the template file, so generate links now
|
// board settings won't be available in the template file, so generate links now
|
||||||
$post['link'] = $config['root'] . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], ($post['thread'] ? $post['thread'] : $post['id'])) . '#' . $post['id'];
|
$post['link'] = $config['root'] . $board['dir'] . $config['dir']['res']
|
||||||
if ($files) $post['src'] = $config['uri_thumb'] . $files[0]->thumb;
|
. sprintf($config['file_page'], ($post['thread'] ? $post['thread'] : $post['id'])) . '#' . $post['id'];
|
||||||
|
|
||||||
|
if ($files) {
|
||||||
|
if ($files[0]->thumb == 'spoiler') {
|
||||||
|
$tn_size = @getimagesize($config['spoiler_image']);
|
||||||
|
$post['src'] = $config['spoiler_image'];
|
||||||
|
$post['thumbwidth'] = $tn_size[0];
|
||||||
|
$post['thumbheight'] = $tn_size[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$post['src'] = $config['uri_thumb'] . $files[0]->thumb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$recent_images[] = $post;
|
$recent_images[] = $post;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user