diff --git a/templates/mod/theme_config.html b/templates/mod/theme_config.html index d82a1f14..044af78e 100644 --- a/templates/mod/theme_config.html +++ b/templates/mod/theme_config.html @@ -13,6 +13,8 @@ {% if settings[conf.name] or (not settings[conf.name] is defined and conf.default) %} checked {% endif %}> + {% elseif conf.type == 'textarea' %} + {% else %} + {% endif %} {% if conf.comment %} {{ conf.comment }} @@ -35,3 +38,8 @@

+ \ No newline at end of file diff --git a/templates/themes/index/hikichanIcon.png b/templates/themes/index/hikichanIcon.png new file mode 100644 index 00000000..75cc3931 Binary files /dev/null and b/templates/themes/index/hikichanIcon.png differ diff --git a/templates/themes/index/hotweels.jpg b/templates/themes/index/hotweels.jpg new file mode 100644 index 00000000..94dda5f7 Binary files /dev/null and b/templates/themes/index/hotweels.jpg differ diff --git a/templates/themes/index/index.css b/templates/themes/index/index.css new file mode 100644 index 00000000..498e9704 --- /dev/null +++ b/templates/themes/index/index.css @@ -0,0 +1,79 @@ +.box-wrap { + max-width: 670px; + min-width: 300px; + margin: 30px auto; + padding: 0; +} +.box { + background: white; + border: 1px solid #98E; + width: 330px; + margin: 8px 0; + padding: 0; +} +.box h2 { + padding: 3px 7px; + font-size: 12pt; +} +.box ul li { + list-style: none; + margin: 0; +} +.mainBox { + background: transparent; + border: 1px solid #008080; + width: 100%; + margin-bottom: 5px; +} +.mainBox h2 { + background: #59A; + color: white; +} +.box.image { + background: transparent; + border: none; + width: 100%; + min-height: 250px; + max-height: 400px; + overflow-x: hidden; + overflow-y: auto;; +} +.box img { + float: left; + margin: 5px; + width: auto !important; + height: 100px !important; + border-radius: 10px; +} +.icon { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 100px; +} +.imageofnow { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 300px; +} +.videoofnow { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 500px; + max-height: 300px; + } +.quoteofnow { + text-align: center; + font-size: 20px; + font-family: -WEBKIT-PICTOGRAPH; +} +.description { + text-align: center; + font-weight: bolder; + } +.boardlinksurl { + float: left; + margin-right: 100px; +} \ No newline at end of file diff --git a/templates/themes/index/index.html b/templates/themes/index/index.html new file mode 100644 index 00000000..d1c73093 --- /dev/null +++ b/templates/themes/index/index.html @@ -0,0 +1,109 @@ +{% filter remove_whitespace %} + + + + + {{ settings.title }} + + + {% if config.url_favicon %}{% endif %} + {% if config.default_stylesheet.1 != '' %}{% endif %} + {% if config.font_awesome %}{% endif %} + {% include 'header.html' %} + + + {{ boardlist.top }} +
+ +

{{ settings.title }}

+
{{ settings.subtitle }}
+
+ {% if config.url_banner %}{% endif %} + +
+
+ Boards + +
+
+
+
+
{{ settings.description }}
+
+ +
+
{{ settings.quoteofnow }}
+
+ +
+
+
+ {% if news|count == 0 %} +

(No news to show.)

+ {% else %} + {% for entry in news %} +

+ {% if entry.subject %} + {{ entry.subject }} + {% else %} + no subject + {% endif %} + — by {{ entry.name }} at {{ entry.time|date(config.post_date, config.timezone) }} +

+

{{ entry.body }}

+ {% endfor %} + {% endif %} +
+

Recent Images

+
+ +
+
+

Latest Posts

+ +
+
+

Stats

+ +
+
+ +
+ + + +{% endfilter %} diff --git a/templates/themes/index/index_dark.css b/templates/themes/index/index_dark.css new file mode 100644 index 00000000..c59214ac --- /dev/null +++ b/templates/themes/index/index_dark.css @@ -0,0 +1,73 @@ +body { + color: #CCCCCC; + background: #1E1E1E; +} + +header div.subtitle, h1 { + color: #CCCCCC; +} + +a:link, a:visited, p.intro a.email span.name { + color: #CCCCCC; + text-decoration: underline; + font-family: sans-serif; +} +a:link:hover, a:visited:hover { + color: #FF0000; + font-family: sans-serif; + text-decoration: underline overline; +} + +.box-wrap { + max-width: 670px; + min-width: 332px; + margin: 30px auto; + overflow: auto; + padding: 0; +} +.box { + background: white; + border: 1px solid #98E; + width: 330px; + margin: 8px 0; + padding: 0; +} +.box ul { + padding: 2px 15px; +} +.box ul li { + list-style: none; + margin: 0; +} +.box.left { + background: #333333; + color: #CCCCCC; + border: #555555 1px solid; + float: left; +} +.box.right { + background: #333333; + color: #CCCCCC; + border: #555555 1px solid; + float: right; +} + +.box h2 { + padding: 3px 7px; + font-size: 12pt; + border: #555555 1px solid; +} +.box.left h2 { + background: #333333; + color: #CCCCCC; + border: #555555 1px solid; +} +.box.right h2 { + background: #333333; + color: #CCCCCC; + border: #555555 1px solid; +} +.box img { + float: none; + margin: 10px auto; +} diff --git a/templates/themes/index/index_fs.css b/templates/themes/index/index_fs.css new file mode 100644 index 00000000..26aed668 --- /dev/null +++ b/templates/themes/index/index_fs.css @@ -0,0 +1,57 @@ +.box-wrap { + max-width: 670px; + min-width: 332px; + margin: 30px auto; + overflow: auto; + padding: 0; +} +.box { + background: white; + border: 1px solid #98E; + width: 330px; + margin: 8px 0; + padding: 0; +} +.box ul { + padding: 2px 15px; +} +.box ul li { + list-style: none; + margin: 0; +} +.box.left { + background: #FDF6AF; + color: #9E914F; + border: 1px solid #9E914F; + float: left; +} +.box.right { + background: #F2DCE5; + color: #525; + border: 1px solid #CA759E; + float: right; +} + +.box h2 { + padding: 3px 7px; + font-size: 12pt; +} +.box img { + float: none; + margin: 10px auto; +} +.box.left h2 { + background: #FEE78F; + color: #9E914F; +} +.box.right h2 { + background: #EB81B4; + color: #F8F8F8; +} + +body { + background: #F7F8F9; +} +header div.subtitle, h1 { + color: #888A8C; +} diff --git a/templates/themes/index/info.php b/templates/themes/index/info.php new file mode 100644 index 00000000..1c7cd7bf --- /dev/null +++ b/templates/themes/index/info.php @@ -0,0 +1,137 @@ + 'Icon', + 'name' => 'icon', + 'type' => 'text', + 'default' => '../templates/themes/index/hikichanIcon.png', + 'size' => 50 + ); + + $theme['config'][] = Array( + 'title' => 'Title', + 'name' => 'title', + 'type' => 'text', + 'default' => 'Welcome to my Image Board', + 'size' => 50 + ); + + $theme['config'][] = Array( + 'title' => 'Subtitle', + 'name' => 'subtitle', + 'type' => 'text', + 'default' => 'What is chaos for the fly is normal for the spider.', + 'size' => 50 + ); + + $theme['config'][] = Array( + 'title' => 'Description', + 'name' => 'description', + 'type' => 'textarea', + 'default' => 'Short description for your website.' + ); + + $theme['config'][] = Array( + 'title' => 'Image of the now.', + 'name' => 'imageofnow', + 'type' => 'text', + 'default' => '../templates/themes/index/hotweels.jpg', + 'size' => 50 + ); + + $theme['config'][] = Array( + 'title' => 'Quote of the now.', + 'name' => 'quoteofnow', + 'type' => 'textarea', + 'default' => '"Great minds discuss ideas; average minds discuss events; small minds discuss people." - QUOTE' + ); + + $theme['config'][] = Array( + 'title' => 'Video of the Now', + 'name' => 'videoofnow', + 'type' => 'text', + 'default' => 'https://www.youtube.com/embed/zndkMAHKjNM', + 'size' => 50 + ); + + $theme['config'][] = Array( + 'title' => '# of recent entries', + 'name' => 'no_recent', + 'type' => 'text', + 'default' => 5, + 'size' => 3, + 'comment' => '(number of recent news entries to display; "0" is infinite)' + ); + + $theme['config'][] = Array( + 'title' => 'Excluded boards', + 'name' => 'exclude', + 'type' => 'text', + 'comment' => '(space seperated)' + ); + + $theme['config'][] = Array( + 'title' => '# of recent images', + 'name' => 'limit_images', + 'type' => 'text', + 'default' => '15', + 'comment' => '(maximum images to display)' + ); + + $theme['config'][] = Array( + 'title' => '# of recent posts', + 'name' => 'limit_posts', + 'type' => 'text', + 'default' => '30', + 'comment' => '(maximum posts to display)' + ); + + $theme['config'][] = Array( + 'title' => 'HTML file', + 'name' => 'html', + 'type' => 'text', + 'default' => 'index.html', + 'comment' => '(eg. "index.html")' + ); + + $theme['config'][] = Array( + 'title' => 'CSS file', + 'name' => 'css', + 'type' => 'text', + 'default' => 'index.css', + 'comment' => '(eg. "index.css")' + ); + + $theme['config'][] = Array( + 'title' => 'CSS stylesheet name', + 'name' => 'basecss', + 'type' => 'text', + 'default' => 'index.css', + 'comment' => '(eg. "index.css" - see templates/themes/index for details)' + ); + + // Unique function name for building everything + $theme['build_function'] = 'index_build'; + $theme['install_callback'] = 'index_install'; + + if (!function_exists('index_install')) { + function index_install($settings) { + if (!is_numeric($settings['limit_images']) || $settings['limit_images'] < 0) + return Array(false, '' . utf8tohtml($settings['limit_images']) . ' is not a non-negative integer.'); + if (!is_numeric($settings['limit_posts']) || $settings['limit_posts'] < 0) + return Array(false, '' . utf8tohtml($settings['limit_posts']) . ' is not a non-negative integer.'); + if (!is_numeric($settings['no_recent']) || $settings['no_recent'] < 0) + return Array(false, '' . utf8tohtml($settings['no_recent']) . ' is not a non-negative integer.'); + } + } + diff --git a/templates/themes/index/theme.php b/templates/themes/index/theme.php new file mode 100644 index 00000000..f9262b82 --- /dev/null +++ b/templates/themes/index/theme.php @@ -0,0 +1,175 @@ +build($action, $settings); + } + + // Wrap functions in a class so they don't interfere with normal Tinyboard operations + class index { + public function build($action, $settings) { + global $config, $_theme; + + if ($action == 'all') { + copy('templates/themes/index/' . $settings['basecss'], $config['dir']['home'] . $settings['css']); + } + + + $this->excluded = explode(' ', $settings['exclude']); + + if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') { + $action = generation_strategy('sb_index', array()); + if ($action == 'delete') { + file_unlink($config['dir']['home'] . $settings['html']); + } + elseif ($action == 'rebuild') { + file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings)); + } + } + if ($action == 'all' || $action == 'news' || $action == 'boards'){ + file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings)); + } + } + + + // Build news page + public function homepage($settings) { + global $config, $board; + + $recent_images = Array(); + $recent_posts = Array(); + $stats = Array(); + + $boards = listBoards(); + + $query = ''; + foreach ($boards as &$_board) { + if (in_array($_board['uri'], $this->excluded)) + continue; + $query .= sprintf("SELECT *, '%s' AS `board` FROM ``posts_%s`` WHERE `files` IS NOT NULL UNION ALL ", $_board['uri'], $_board['uri']); + } + $query = preg_replace('/UNION ALL $/', 'ORDER BY `time` DESC LIMIT ' . (int)$settings['limit_images'], $query); + + if ($query == '') { + error(_("Can't build the Index theme, because there are no boards to be fetched.")); + } + + $query = query($query) or error(db_error()); + + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { + openBoard($post['board']); + + if (isset($post['files'])) + $files = json_decode($post['files']); + + if ($files[0]->file == 'deleted' || $files[0]->thumb == 'file') continue; + + // board settings won't be available in the template file, so generate links now + $post['link'] = $config['root'] . $board['dir'] . $config['dir']['res'] + . link_for($post) . '#' . $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; + $post['thumbwidth'] = $files[0]->thumbwidth; + $post['thumbheight'] = $files[0]->thumbheight; + } + } + + $recent_images[] = $post; + } + + + $query = ''; + foreach ($boards as &$_board) { + if (in_array($_board['uri'], $this->excluded)) + continue; + $query .= sprintf("SELECT *, '%s' AS `board` FROM ``posts_%s`` UNION ALL ", $_board['uri'], $_board['uri']); + } + $query = preg_replace('/UNION ALL $/', 'ORDER BY `time` DESC LIMIT ' . (int)$settings['limit_posts'], $query); + $query = query($query) or error(db_error()); + + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { + openBoard($post['board']); + + $post['link'] = $config['root'] . $board['dir'] . $config['dir']['res'] . link_for($post) . '#' . $post['id']; + if ($post['body'] != "") + $post['snippet'] = pm_snippet($post['body'], 30); + else + $post['snippet'] = "" . _("(no comment)") . ""; + $post['board_name'] = $board['name']; + + $recent_posts[] = $post; + } + + // Total posts + $query = 'SELECT SUM(`top`) FROM ('; + foreach ($boards as &$_board) { + if (in_array($_board['uri'], $this->excluded)) + continue; + $query .= sprintf("SELECT MAX(`id`) AS `top` FROM ``posts_%s`` UNION ALL ", $_board['uri']); + } + $query = preg_replace('/UNION ALL $/', ') AS `posts_all`', $query); + $query = query($query) or error(db_error()); + $stats['total_posts'] = number_format($query->fetchColumn()); + + // Unique IPs + $query = 'SELECT COUNT(DISTINCT(`ip`)) FROM ('; + foreach ($boards as &$_board) { + if (in_array($_board['uri'], $this->excluded)) + continue; + $query .= sprintf("SELECT `ip` FROM ``posts_%s`` UNION ALL ", $_board['uri']); + } + $query = preg_replace('/UNION ALL $/', ') AS `posts_all`', $query); + $query = query($query) or error(db_error()); + $stats['unique_posters'] = number_format($query->fetchColumn()); + + // Active content + $query = 'SELECT DISTINCT(`files`) FROM ('; + foreach ($boards as &$_board) { + if (in_array($_board['uri'], $this->excluded)) + continue; + $query .= sprintf("SELECT `files` FROM ``posts_%s`` UNION ALL ", $_board['uri']); + } + $query = preg_replace('/UNION ALL $/', ' WHERE `num_files` > 0) AS `posts_all`', $query); + $query = query($query) or error(db_error()); + $files = $query->fetchAll(); + $stats['active_content'] = 0; + foreach ($files as &$file) { + preg_match_all('/"size":([0-9]*)/', $file[0], $matches); + $stats['active_content'] += array_sum($matches[1]); + } + + //news entries + $settings['no_recent'] = (int) $settings['no_recent']; + $query = query("SELECT * FROM ``news`` ORDER BY `time` DESC" . ($settings['no_recent'] ? ' LIMIT ' . $settings['no_recent'] : '')) or error(db_error()); + $news = $query->fetchAll(PDO::FETCH_ASSOC); + + return Element('themes/index/index.html', Array( + 'settings' => $settings, + 'config' => $config, + 'boardlist' => createBoardlist(), + 'recent_images' => $recent_images, + 'recent_posts' => $recent_posts, + 'stats' => $stats, + 'news' => $news, + 'boards' => listBoards() + )); + } + }; + +?> diff --git a/templates/themes/index/thumb.png b/templates/themes/index/thumb.png new file mode 100644 index 00000000..c15dc3fa Binary files /dev/null and b/templates/themes/index/thumb.png differ