Browse Source

Revert "Revert "Add SFW overboard theme""

This reverts commit 9acdacbb35.
pull/40/head
towards-a-new-leftypol 3 years ago
committed by towards-a-new-leftypol
parent
commit
6735125ffa
  1. 2
      inc/instance-config.php
  2. 11
      templates/themes/catalog/info.php
  3. 38
      templates/themes/catalog/theme.php
  4. 23
      templates/themes/overboards/info.php
  5. 158
      templates/themes/overboards/overboard.js
  6. 34
      templates/themes/overboards/overboards.php
  7. 235
      templates/themes/overboards/theme.php
  8. BIN
      templates/themes/overboards/thumb.png

2
inc/instance-config.php

@ -27,6 +27,8 @@ $config['boards'] = array(
$config['prepended_foreign_boards'] = array(
'overboard' => '/overboard/',
'sfw' => '/sfw/',
'alt' => '/alt/',
'cytube' => 'https://tv.leftypol.org/'
);

11
templates/themes/catalog/info.php

@ -84,18 +84,11 @@
'comment' => 'Check this if you wish to show a nice tooltip with info about the thread on mouse over.'
);
$theme['config'][] = Array(
'title' => 'Build overboard catalog',
'title' => 'Build overboard catalogs',
'name' => 'has_overboard',
'type' => 'checkbox',
'default' => false,
'comment' => 'Check this if you wish to create a catalog for the overboard.'
);
$theme['config'][] = Array(
'title' => 'Overboard location (default \'overboard\')',
'name' => 'overboard_location',
'type' => 'text',
'default' => 'overboard',
'comment' => 'Fill in the location of the overboard directory. Default is \'overboard\' which corresponds to ./overboard'
'comment' => 'Check this if you wish to create a catalog for the overboard. Requires Overboards theme.'
);
$theme['config'][] = Array(
'title' => 'Max posts in catalog overboard',

38
templates/themes/catalog/theme.php

@ -9,6 +9,11 @@
$b = new Catalog($settings);
$boards = explode(' ', $settings['boards']);
if (isset($settings['has_overboard']) && $settings['has_overboard']) {
// Include overboard settings so that we can find them all and process exclusions
require "templates/themes/overboards/overboards.php";
}
// Possible values for $action:
// - all (rebuild everything, initialization)
// - news (news has been updated)
@ -28,14 +33,16 @@
}
}
if(isset($settings['has_overboard']) && $settings['has_overboard']) {
$board = $settings['overboard_location'];
$action = generation_strategy("sb_catalog", array($board));
if ($action == 'delete') {
file_unlink($config['dir']['home'] . $board . '/catalog.html');
file_unlink($config['dir']['home'] . $board . '/index.rss');
}
elseif ($action == 'rebuild') {
$b->buildOverboardCatalog($settings, $boards);
foreach ($overboards_config as &$overboard) {
$included_boards = array_diff(listBoards(true), $overboard['exclude']);
$action = generation_strategy("sb_catalog", array($overboard));
if ($action == 'delete') {
file_unlink($config['dir']['home'] . $overboard . '/catalog.html');
file_unlink($config['dir']['home'] . $overboard . '/index.rss');
}
elseif ($action == 'rebuild') {
$b->buildOverboardCatalog($overboard['uri'], $settings, $included_boards);
}
}
}
} elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') || ($settings['update_on_posts'] && $action == 'post-delete')
@ -51,7 +58,12 @@
print_err("catalog_build calling Catalog.build 2");
$b->build($settings, $board);
if(isset($settings['has_overboard']) && $settings['has_overboard']) {
$b->buildOverboardCatalog($settings, $boards);
foreach ($overboards_config as &$overboard) {
if ($overboard['uri'] == $board) {
$included_boards = array_diff(listBoards(true), $overboard['exclude']);
$b->buildOverboardCatalog($board, $settings, $included_boards);
}
}
}
}
}
@ -297,7 +309,7 @@
$recent_posts = $this->generateRecentPosts($threads);
$this->saveForBoard($randSettings['uri'], $recent_posts,
$config['root'] . $randSettings['uri']);
$config['root'] . $randSettings['uri'], true);
}
/**
@ -347,10 +359,8 @@
/**
* Build and save the HTML of the catalog for the overboard
*/
public function buildOverboardCatalog($settings, $boards) {
public function buildOverboardCatalog($board_name, $settings, $boards) {
global $config;
$board_name = $settings['overboard_location'];
if (array_key_exists($board_name, $this->threadsCache)) {
$threads = $this->threadsCache[$board_name];
@ -372,7 +382,7 @@
// Generate data for the template
$recent_posts = $this->generateRecentPosts($threads);
$this->saveForBoard($board_name, $recent_posts, '/' . $settings['overboard_location'], true);
$this->saveForBoard($board_name, $recent_posts, '/' . $board_name, true);
// Build the overboard JSON outputs
if ($config['api']['enabled']) {

23
templates/themes/overboards/info.php

@ -0,0 +1,23 @@
<?php
// Basic theme properties
$theme = array(
'name' => 'Overboards',
// Description (you can use Tinyboard markup here)
'description' => 'Add one or more overboards, such as a normal overboard and a SFW overboard.',
'version' => 'v0.1',
// Unique function name for building and installing whatever's necessary
'build_function' => 'overboards_build',
);
// Theme configuration
$theme['config'] = array(
array(
'title' => 'Edit overboards.php manually to add, remove or modify overboards',
'name' => 'instruct1',
'type' => 'checkbox',
'default' => false,
'comment' => 'Located at templates/themes/overboards/overboards.php'
),
);

158
templates/themes/overboards/overboard.js

@ -0,0 +1,158 @@
$(document).ready(function() {
var cachedPages = [],
loading = false,
timer = null;
// Load data from HTML5 localStorage
var hiddenBoards = JSON.parse(localStorage.getItem('hiddenboards'));
var storeHiddenBoards = function() {
localStorage.setItem('hiddenboards', JSON.stringify(hiddenBoards));
};
// No board are hidden by default
if (!hiddenBoards) {
hiddenBoards = {};
storeHiddenBoards();
}
// Hide threads from the same board and remember for next time
var onHideClick = function(e) {
e.preventDefault();
var board = $(this).parent().next().data('board'),
threads = $('[data-board="'+board+'"]:not([data-cached="yes"])'),
btns = threads.prev().find('.threads-toggle'),
hrs = btns.next();
if (hiddenBoards[board]) {
threads.show();
btns.find('.threads-toggle').html(_('(hide threads from this board)'));
hrs.hide();
} else {
threads.hide();
btns.html(_('(show threads from this board)'));
hrs.show();
}
hiddenBoards[board] = !hiddenBoards[board];
storeHiddenBoards();
};
// Add a hiding link and horizontal separator to each thread
var addHideButton = function() {
var board = $(this).next().data('board'),
// Create the link and separator
button = $('<a href="#" class="unimportant threads-toggle"></a>')
.click(onHideClick),
myHr = $('<hr />');
// Insert them after the board name
$(this).append(' ').append(button).append(myHr);
if (hiddenBoards[board]) {
button.html(_('(show threads from this board)'));
$(this).next().hide();
} else {
button.html(_('(hide threads from this board)'));
myHr.hide();
}
};
$('h2').each(addHideButton);
var appendThread = function(elem, data) {
var boardLink = $('<h2><a href="' + modRoot + data.board + '/">/' +
data.board + '/</a></h2>');
// Push the thread after the currently last one
$('div[id*="thread_"]').last()
.after(elem.data('board', data.board)
.data('cached', 'no')
.show());
// Add the obligatory board link
boardLink.insertBefore(elem);
// Set up the hiding link
addHideButton.call(boardLink);
// Trigger an event to let the world know that we have a new thread aboard
$(document).trigger('new_post', elem);
};
var attemptLoadNext = function() {
if (!ukko_overflow.length) {
$('.pages').show().html(_('No more threads to display'));
return;
}
var viewHeight = $(window).scrollTop() + $(window).height(),
pageHeight = $(document).height();
// Keep loading deferred threads as long as we're close to the bottom of the
// page and there are threads remaining
while(viewHeight + 1000 > pageHeight && !loading && ukko_overflow.length > 0) {
// Take the first unloaded post
var post = ukko_overflow.shift(),
page = modRoot + post.board + '/' + post.page;
var thread = $('div#thread_' + post.id + '[data-board="' + post.board + '"]');
// Check that the thread hasn't been inserted yet
if (thread.length && thread.data('cached') !== 'yes') {
continue;
}
// Check if we've already downloaded the index page on which this thread
// is located
if ($.inArray(page, cachedPages) !== -1) {
if (thread.length) {
appendThread(thread, post);
}
// Otherwise just load the page and cache its threads
} else {
// Make sure that no other thread does the job that we're about to do
loading = true;
$('.pages').show().html(_('Loading…'));
// Retrieve the page from the server
$.get(page, function(data) {
cachedPages.push(page);
// Cache each retrieved thread
$(data).find('div[id*="thread_"]').each(function() {
var thread_id = $(this).attr('id').replace('thread_', '');
// Check that this thread hasn't already been loaded somehow
if ($('div#thread_' + thread_id + '[data-board="' +
post.board + '"]').length)
{
return;
}
// Hide the freshly loaded threads somewhere at the top
// of the page for now
$('form[name="postcontrols"]')
.prepend($(this).hide()
.data('cached', 'yes')
.data('data-board', post.board));
});
// Find the current thread in the newly retrieved ones
thread = $('div#thread_' + post.id + '[data-board="' +
post.board + '"][data-cached="yes"]');
if (thread.length) {
appendThread(thread, post);
}
// Release the lock
loading = false;
$('.pages').hide().html('');
});
break;
}
}
clearTimeout(timer);
// Check again in one second
timer = setTimeout(attemptLoadNext, 1000);
};
attemptLoadNext();
});

34
templates/themes/overboards/overboards.php

@ -0,0 +1,34 @@
<?php
/*
* When adding a new board, rebuild this theme. If necessary, reconfigure the catalog theme.
* Exclude list is a PHP array e.g. 'exclude' => array('b', 'games', 'music')
*/
$thread_limit = 30;
// Define list of overboards
$overboards_config = array(
array(
'title' => 'Overboard',
'uri' => 'overboard',
'subtitle' => '30 most recently bumped threads',
'exclude' => array('assembly', 'assembly_archive', 'gulag'),
'thread_limit' => $thread_limit,
),
array(
'title' => 'SFW Overboard',
'uri' => 'sfw',
'subtitle' => '30 most recently bumped threads from work-safe boards',
'exclude' => array('assembly', 'assembly_archive', 'gulag', 'b'),
'thread_limit' => $thread_limit,
),
array(
'title' => 'Alternate Overboard',
'uri' => 'alt',
'subtitle' => '30 most recently bumped threads from smaller interest boards',
'exclude' => array('assembly', 'assembly_archive', 'gulag', 'leftypol', 'b', 'meta'),
'thread_limit' => $thread_limit,
),
);
?>

235
templates/themes/overboards/theme.php

@ -0,0 +1,235 @@
<?php
require 'info.php';
/**
* Generate the board's HTML and move it and its JavaScript in place, whence
* it's served
*/
function overboards_build($action, $settings) {
global $config;
if ($action !== 'all' && $action !== 'post' && $action !== 'post-thread' &&
$action !== 'post-delete')
{
return;
}
if ($config['smart_build']) {
file_unlink($settings['uri'] . '/index.html');
} else {
require 'overboards.php';
$overboards = new overboards($overboards_config);
foreach ($overboards_config as &$overboard) {
if (!file_exists($overboard['uri'])) {
@mkdir($overboard['uri'], 0777) or error("Couldn't create {$overboard['uri']}. Check permissions.", true);
}
// Copy the generated board HTML to its place
file_write($overboard['uri'] . '/index.html', $overboards->build($overboard));
file_write($overboard['uri'] . '/overboard.js',
Element('themes/overboards/overboard.js', array()));
}
}
}
/**
* Encapsulation of the theme's internals
*/
class overboards {
private $settings;
function __construct($settings) {
$this->settings = $this->parseSettings($settings);
}
/**
* Parse and validate configuration parameters passed from the UI
*/
private function parseSettings(&$settings) {
foreach ($settings as &$overboard) {
if (!is_int($overboard['thread_limit']) || $overboard['thread_limit'] < 1)
{
error('thread_limit must be an integer above 1.', true);
}
if (!is_array($overboard['exclude']))
{
error('Exclude list must be array of strings.', true);
}
foreach ($overboard['exclude'] as &$board) {
if (!is_string($board)){
error('Exclude list must be array of strings.', true);
}
}
}
return $settings;
}
/**
* Obtain list of all threads from all non-excluded boards
*/
private function fetchThreads($overboard) {
$query = '';
$boards = listBoards(true);
foreach ($boards as $b) {
if (in_array($b, $overboard['exclude']))
continue;
// Threads are those posts that have no parent thread
$query .= "SELECT *, '$b' AS `board` FROM ``posts_$b`` " .
"WHERE `thread` IS NULL UNION ALL ";
}
$query = preg_replace('/UNION ALL $/', 'ORDER BY `bump` DESC', $query);
$result = query($query) or error(db_error());
return $result->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Retrieve all replies to a given thread
*/
private function fetchReplies($board, $thread_id, $preview_count) {
$query = prepare("SELECT * FROM (SELECT * FROM ``posts_$board`` WHERE `thread` = :id ORDER BY `time` DESC LIMIT :limit) as
t ORDER BY t.time ASC");
$query->bindValue(':id', $thread_id, PDO::PARAM_INT);
$query->bindValue(':limit', $preview_count, PDO::PARAM_INT);
$query->execute() or error(db_error($query));
return $query->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Retrieve count of images and posts in a thread
*/
private function fetchThreadCount($board, $thread_id, $preview_count) {
$query = prepare("SELECT SUM(t.num_files) as file_count, COUNT(t.id) as post_count FROM (SELECT * FROM ``posts_$board`` WHERE `thread` = :id ORDER BY `time` DESC LIMIT :offset , 18446744073709551615) as t;");
$query->bindValue(':id', $thread_id, PDO::PARAM_INT);
$query->bindValue(':offset', $preview_count, PDO::PARAM_INT);
$query->execute() or error(db_error($query));
return $query->fetch(PDO::FETCH_ASSOC);
}
/**
* Build the HTML of a single thread in the catalog
*/
private function buildOne($post, $mod = false) {
global $config;
openBoard($post['board']);
$thread = new Thread($post, $mod ? '?/' : $config['root'], $mod);
// Number of replies to a thread that are displayed beneath it
$preview_count = $post['sticky'] ? $config['threads_preview_sticky'] :
$config['threads_preview'];
$replies = $this->fetchReplies($post['board'], $post['id'], $preview_count);
$disp_replies = $replies;
foreach ($disp_replies as $reply) {
// Append the reply to the thread as it's being built
$thread->add(new Post($reply, $mod ? '?/' : $config['root'], $mod));
}
$threadCount = $this->fetchThreadCount($post['board'], $post['id'], $preview_count);
$thread->omitted = $threadCount['post_count'];
$thread->omitted_images = $threadCount['file_count'];
// Board name and link
$html = '<h2><a href="' . $config['root'] . $post['board'] . '/">/' .
$post['board'] . '/</a></h2>';
// The thread itself
$html .= $thread->build(true);
return $html;
}
/**
* Query the required information and generate the HTML
*/
public function build($overboard, $mod = false) {
if (!isset($this->settings)) {
error('Theme is not configured properly.');
}
global $config;
$html = '';
$overflow = array();
// Fetch threads from all boards and chomp the first 'n' posts, depending
// on the setting
$threads = $this->fetchThreads($overboard);
$total_count = count($threads);
// Top threads displayed on load
$top_threads = array_splice($threads, 0, $overboard['thread_limit']);
// Number of processed threads by board
$counts = array();
// Output threads up to the specified limit
foreach ($top_threads as $post) {
if (array_key_exists($post['board'], $counts)) {
++$counts[$post['board']];
} else {
$counts[$post['board']] = 1;
}
$html .= $this->buildOne($post, $mod);
}
foreach ($threads as $post) {
if (array_key_exists($post['board'], $counts)) {
++$counts[$post['board']];
} else {
$counts[$post['board']] = 1;
}
$page = 'index';
$board_page = floor($counts[$post['board']] / $config['threads_per_page']);
if ($board_page > 0) {
$page = $board_page + 1;
}
$overflow[] = array(
'id' => $post['id'],
'board' => $post['board'],
'page' => $page . '.html'
);
}
$html .= '<script>var ukko_overflow = ' . json_encode($overflow) . '</script>';
$html .= '<script type="text/javascript" src="/'.$overboard['uri'].'/overboard.js"></script>';
return Element('index.html', array(
'config' => $config,
'board' => array(
'dir' => $overboard['uri'] . "/",
'url' => $overboard['uri'],
'title' => $overboard['title'],
'subtitle' => str_replace('%s', $overboard['thread_limit'],
strval(min($overboard['subtitle'], $total_count))),
),
'no_post_form' => true,
'body' => $html,
'mod' => $mod,
'boardlist' => createBoardlist($mod),
));
}
};
if (!function_exists('array_column')) {
/**
* Pick out values from subarrays by given key
*/
function array_column($array, $key) {
$result = [];
foreach ($array as $val) {
$result[] = $val[$key];
}
return $result;
}
}

BIN
templates/themes/overboards/thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Loading…
Cancel
Save