diff --git a/themes/okebooru/admin.theme.php b/themes/okebooru/admin.theme.php
new file mode 100644
index 00000000..dc446b38
--- /dev/null
+++ b/themes/okebooru/admin.theme.php
@@ -0,0 +1,11 @@
+disable_left();
+ parent::display_page();
+ }
+}
diff --git a/themes/okebooru/clip.woff2 b/themes/okebooru/clip.woff2
new file mode 100644
index 00000000..77634518
Binary files /dev/null and b/themes/okebooru/clip.woff2 differ
diff --git a/themes/okebooru/comment.theme.php b/themes/okebooru/comment.theme.php
new file mode 100644
index 00000000..3399a489
--- /dev/null
+++ b/themes/okebooru/comment.theme.php
@@ -0,0 +1,127 @@
+disable_left();
+
+ // parts for the whole page
+ $prev = $page_number - 1;
+ $next = $page_number + 1;
+
+ $h_prev = ($page_number <= 1) ? "Prev" :
+ "Prev ";
+ $h_index = "Index ";
+ $h_next = ($page_number >= $total_pages) ? "Next" :
+ "Next ";
+
+ $nav = "$h_prev | $h_index | $h_next";
+
+ $page->set_title("Comments");
+ $page->set_heading("Comments");
+ $page->add_block(new Block("Navigation", $nav, "left"));
+ $this->display_paginator($page, "comment/list", null, $page_number, $total_pages);
+
+ // parts for each image
+ $position = 10;
+
+ $comment_captcha = $config->get_bool('comment_captcha');
+ $comment_limit = $config->get_int("comment_list_count", 10);
+
+ foreach ($images as $pair) {
+ $image = $pair[0];
+ $comments = $pair[1];
+
+ $thumb_html = $this->build_thumb_html($image);
+
+ $s = " ";
+ $un = $image->get_owner()->name;
+ $t = "";
+ foreach ($image->get_tag_array() as $tag) {
+ $u_tag = url_escape($tag);
+ $t .= "".html_escape($tag)." ";
+ }
+ $p = autodate($image->posted);
+
+ $r = Extension::is_enabled(RatingsInfo::KEY) ? "Rating ".Ratings::rating_to_human($image->rating) : "";
+ $comment_html = "Date $p $s User $un $s $rTags $t
";
+
+ $comment_count = count($comments);
+ if ($comment_limit > 0 && $comment_count > $comment_limit) {
+ //$hidden = $comment_count - $comment_limit;
+ $comment_html .= "
showing $comment_limit of $comment_count comments
";
+ $comments = array_slice($comments, -$comment_limit);
+ }
+ foreach ($comments as $comment) {
+ $comment_html .= $this->comment_to_html($comment);
+ }
+ if ($can_post) {
+ if (!$user->is_anonymous()) {
+ $comment_html .= $this->build_postbox($image->id);
+ } else {
+ if (!$comment_captcha) {
+ $comment_html .= $this->build_postbox($image->id);
+ } else {
+ $comment_html .= "Add Comment ";
+ }
+ }
+ }
+
+ $html = "
+
+ $thumb_html
+ $comment_html
+
+ ";
+
+
+ $page->add_block(new Block(" ", $html, "main", $position++));
+ }
+ }
+
+ public function display_recent_comments(array $comments)
+ {
+ // no recent comments in this theme
+ }
+
+
+ protected function comment_to_html(Comment $comment, bool $trim=false): string
+ {
+ global $user;
+
+ $tfe = new TextFormattingEvent($comment->comment);
+ send_event($tfe);
+
+ //$i_uid = $comment->owner_id;
+ $h_name = html_escape($comment->owner_name);
+ //$h_poster_ip = html_escape($comment->poster_ip);
+ $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted);
+ $i_comment_id = $comment->comment_id;
+ $i_image_id = $comment->image_id;
+ $h_posted = autodate($comment->posted);
+
+ $h_userlink = "$h_name ";
+ $h_del = "";
+ if ($user->can(Permissions::DELETE_COMMENT)) {
+ $comment_preview = substr(html_unescape($tfe->stripped), 0, 50);
+ $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview");
+ $h_delete_script = html_escape("return confirm($j_delete_confirm_message);");
+ $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id");
+ $h_del = " - Del ";
+ }
+ //$h_imagelink = $trim ? ">>> \n" : "";
+ if ($trim) {
+ return "";
+ } else {
+ return "
+
+ ";
+ }
+ }
+}
diff --git a/themes/okebooru/ext_manager.theme.php b/themes/okebooru/ext_manager.theme.php
new file mode 100644
index 00000000..4ca58ccc
--- /dev/null
+++ b/themes/okebooru/ext_manager.theme.php
@@ -0,0 +1,16 @@
+disable_left();
+ parent::display_table($page, $extensions, $editable);
+ }
+
+ public function display_doc(Page $page, ExtensionInfo $info)
+ {
+ $page->disable_left();
+ parent::display_doc($page, $info);
+ }
+}
diff --git a/themes/okebooru/favicon.ico b/themes/okebooru/favicon.ico
new file mode 100644
index 00000000..a5ffdcd9
Binary files /dev/null and b/themes/okebooru/favicon.ico differ
diff --git a/themes/okebooru/index.theme.php b/themes/okebooru/index.theme.php
new file mode 100644
index 00000000..73a2da10
--- /dev/null
+++ b/themes/okebooru/index.theme.php
@@ -0,0 +1,53 @@
+display_shortwiki($page);
+
+ $this->display_page_header($page, $images);
+
+ $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms);
+ $page->add_block(new Block("Search", $nav, "left", 0));
+
+ if (count($images) > 0) {
+ $this->display_page_images($page, $images);
+ } else {
+ $this->display_error(404, "No Images Found", "No images were found to match the search criteria");
+ }
+ }
+
+ /**
+ * #param string[] $search_terms
+ */
+ protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string
+ {
+ $h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms));
+ $h_search_link = make_link();
+ return "
+
+
";
+ }
+
+ /**
+ * #param Image[] $images
+ */
+ protected function build_table(array $images, ?string $query): string
+ {
+ $h_query = html_escape($query);
+ $table = "";
+ foreach ($images as $image) {
+ $table .= "\t" . $this->build_thumb_html($image) . " \n";
+ }
+ $table .= "
";
+ return $table;
+ }
+}
diff --git a/themes/okebooru/page.class.php b/themes/okebooru/page.class.php
new file mode 100644
index 00000000..ed911949
--- /dev/null
+++ b/themes/okebooru/page.class.php
@@ -0,0 +1,166 @@
+, updated by Daniel Oaks , modified for Okebooru by butterbutt
+ * Link: https://code.shishnet.org/shimmie2/
+ * License: GPLv2
+ * Description: This is the Danbooru 2 theme with some fun modifications
+ * specifically for Okebooru .
+ */
+//Small changes added by zshall
+//Changed CSS and layout to make shimmie look even more like danbooru
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+Danbooru 2 Theme - Notes (Bzchan)
+
+Files: default.php, style.css
+
+How to use a theme
+- Copy the danbooru2 folder with all its contained files into the "themes"
+ directory in your shimmie installation.
+- Log into your shimmie and change the Theme in the Board Config to your
+ desired theme.
+
+Changes in this theme include
+- Adding and editing various elements in the style.css file.
+- $site_name and $front_name retreival from config added.
+- $custom_link and $title_link preparation just before html is outputed.
+- Altered outputed html to include the custom links and removed heading
+ from being displayed (subheading is still displayed)
+- Note that only the sidebar has been left aligned. Could not properly
+ left align the main block because blocks without headers currently do
+ not have ids on there div elements. (this was a problem because
+ paginator block must be centered and everything else left aligned)
+
+Tips
+- You can change custom links to point to whatever pages you want as well as adding
+ more custom links.
+- The main title link points to the Front Page set in your Board Config options.
+- The text of the main title is the Title set in your Board Config options.
+- Themes make no changes to your database or main code files so you can switch
+ back and forward to other themes all you like.
+
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+class Page extends BasePage
+{
+ public $left_enabled = true;
+ public function disable_left()
+ {
+ $this->left_enabled = false;
+ }
+
+ public function render()
+ {
+ global $config;
+
+ list($nav_links, $sub_links) = $this->get_nav_links();
+
+ $left_block_html = "";
+ $user_block_html = "";
+ $main_block_html = "";
+ $sub_block_html = "";
+
+ foreach ($this->blocks as $block) {
+ switch ($block->section) {
+ case "left":
+ $left_block_html .= $block->get_html(true);
+ break;
+ case "user":
+ $user_block_html .= $block->body; // $this->block_to_html($block, true);
+ break;
+ case "subheading":
+ $sub_block_html .= $block->body; // $this->block_to_html($block, true);
+ break;
+ case "main":
+ if ($block->header == "Images") {
+ $block->header = " ";
+ }
+ $main_block_html .= $block->get_html(false);
+ break;
+ default:
+ print "error: {$block->header} using an unknown section ({$block->section})";
+ break;
+ }
+ }
+
+ if (empty($this->subheading)) {
+ $subheading = "";
+ } else {
+ $subheading = "
{$this->subheading}
";
+ }
+
+ $site_name = $config->get_string(SetupConfig::TITLE); // bzchan: change from normal default to get title for top of page
+ $main_page = $config->get_string(SetupConfig::MAIN_PAGE); // bzchan: change from normal default to get main page for top of page
+
+ $custom_links = "";
+ foreach ($nav_links as $nav_link) {
+ $custom_links .= "".$this->navlinks($nav_link->link, $nav_link->description, $nav_link->active)." ";
+ }
+
+ $custom_sublinks = "";
+ if (!empty($sub_links)) {
+ $custom_sublinks = "";
+ foreach ($sub_links as $nav_link) {
+ $custom_sublinks .= "
".$this->navlinks($nav_link->link, $nav_link->description, $nav_link->active)." ";
+ }
+ $custom_sublinks .= "";
+ }
+
+ // bzchan: failed attempt to add heading after title_link (failure was it looked bad)
+ //if($this->heading==$site_name)$this->heading = '';
+ //$title_link = "";
+
+ // bzchan: prepare main title link
+ $title_link = "";
+
+ if ($this->left_enabled) {
+ $left = "$left_block_html ";
+ $withleft = "withleft";
+ } else {
+ $left = "";
+ $withleft = "noleft";
+ }
+
+ $flash_html = $this->flash ? "".nl2br(html_escape(implode("\n", $this->flash)))." " : "";
+ $head_html = $this->head_html();
+ $footer_html = $this->footer_html();
+
+ print <<
+
+ $head_html
+
+
+ $subheading
+ $sub_block_html
+ $left
+
+ $flash_html
+ $main_block_html
+
+
+
+
+EOD;
+ }
+
+ public function navlinks(Link $link, string $desc, bool $active): ?string
+ {
+ $html = null;
+ if ($active) {
+ $html = "{$desc} ";
+ } else {
+ $html = "{$desc} ";
+ }
+
+ return $html;
+ }
+}
diff --git a/themes/okebooru/robots.txt b/themes/okebooru/robots.txt
new file mode 100644
index 00000000..bb3d05b6
--- /dev/null
+++ b/themes/okebooru/robots.txt
@@ -0,0 +1,27 @@
+User-agent: *
+Allow: /
+Disallow: /artist
+Disallow: /artist_commentaries
+Disallow: /comment
+Disallow: /explore
+Disallow: /forum
+Disallow: /inline
+Disallow: /forum_topics
+Disallow: /note
+Disallow: /pool
+Disallow: /post
+Disallow: /session
+Disallow: /static
+Disallow: /tag
+Disallow: /tag_alias
+Disallow: /tag_implication
+Disallow: /uploads
+Disallow: /user_upgrades
+Disallow: /user
+Disallow: /wiki
+Disallow: /report
+Disallow: /job_task
+Disallow: /help
+Disallow: /admin
+Disallow: /dmail
+Disallow: /batch
diff --git a/themes/okebooru/style.css b/themes/okebooru/style.css
new file mode 100644
index 00000000..a3dde054
--- /dev/null
+++ b/themes/okebooru/style.css
@@ -0,0 +1,648 @@
+span#left, span#right, span.flicker, span.fast-flicker {
+ font-family: clip, "Arial", sans-serif;
+ font-size: clamp(4rem, 1.428rem + 14.285vw, 6rem);
+}
+
+span.small {
+ font-size: 2.5rem !important;
+}
+
+span#left {
+ color: #ffe6ff;
+ text-shadow: 0 0 0.6rem #ffe6ff, 0 0 1.5rem #ff65bd,
+ -0.2rem 0.1rem 1rem #ff65bd, 0.2rem 0.1rem 1rem #ff65bd,
+ 0 -0.5rem 2rem #ff2483, 0 0.5rem 3rem #ff2483;
+ animation: shine-one 2s forwards, flicker 3s infinite;
+}
+
+span#right {
+ color: #b2f3f2;
+ text-shadow: 0 0 0.6rem #b2f3f2, 0 0 1.5rem #75f1f1,
+ -0.2rem 0.1rem 1rem #75f1f1, 0.2rem 0.1rem 1rem #75f1f1,
+ 0 -0.5rem 2rem #1cf3f1, 0 0.5rem 3rem #1cf3f1;
+ animation: shine-two 2s forwards, flicker 6s infinite;
+}
+
+h1 a:hover {
+ text-decoration: none;
+}
+
+h1#site-title span {
+ padding: 1em 0 0 0;
+ text-align: left;
+ margin: 0;
+ color: #ffffff;
+ text-shadow: 0 0 0.6rem #ffffff, 0 0 1.5rem #ffffff,
+ -0.2rem 0.1rem 1rem #ffffff, 0.2rem 0.1rem 1rem #ffffff,
+ 0 -0.5rem 2rem #e6e6e6, 0 0.5rem 3rem #e6e6e6;
+}
+
+h1#site-title span a {
+ color: #e1c6ff;
+ text-shadow: 0 0 0.6rem #bf86ff, 0 0 1.5rem #bf86ff,
+ -0.2rem 0.1rem 1rem #bf86ff, 0.2rem 0.1rem 1rem #8737e2,
+ 0 -0.5rem 2rem #8737e2, 0 0.5rem 3rem #8737e2;
+}
+
+h1#site-title span a:active {
+ color: #faf5ff;
+ text-decoration: none;
+}
+
+.flicker {
+ animation: shine-two 2s forwards, blink-two 10s 1s infinite;
+}
+
+.fast-flicker {
+ animation: shine-one 2s forwards, blink-one 3s 2s infinite;
+}
+@keyframes shine-one {
+ 0% {
+ color: #6b1839;
+ text-shadow: none;
+ }
+ 100% {
+ color: #ffe6ff;
+ text-shadow: 0 0 0.6rem #ffe6ff, 0 0 1.5rem #ff65bd,
+ -0.2rem 0.1rem 1rem #ff65bd, 0.2rem 0.1rem 1rem #ff65bd,
+ 0 -0.5rem 2rem #ff2483, 0 0.5rem 3rem #ff2483;
+ }
+}
+
+@keyframes shine-two {
+ 0% {
+ color: #178685;
+ text-shadow: none;
+ }
+ 100% {
+ color: #b2f3f2;
+ text-shadow: 0 0 0.6rem #b2f3f2, 0 0 1.5rem #75f1f1,
+ -0.2rem 0.1rem 1rem #75f1f1, 0.2rem 0.1rem 1rem #75f1f1,
+ 0 -0.5rem 2rem #1cf3f1, 0 0.5rem 3rem #1cf3f1;
+ }
+}
+
+@keyframes blink-one {
+ 0%,
+ 22%,
+ 36%,
+ 75% {
+ color: #ffe6ff;
+ text-shadow: 0 0 0.6rem #ffe6ff, 0 0 1.5rem #ff65bd,
+ -0.2rem 0.1rem 1rem #ff65bd, 0.2rem 0.1rem 1rem #ff65bd,
+ 0 -0.5rem 2rem #ff2483, 0 0.5rem 3rem #ff2483;
+ }
+ 28%,
+ 33% {
+ color: #ff65bd;
+ text-shadow: none;
+ }
+ 82%,
+ 97% {
+ color: #ff2483;
+ text-shadow: none;
+ }
+}
+
+@keyframes blink-two {
+ 0%,
+ 22%,
+ 36%,
+ 75% {
+ color: #ddfefd;
+ text-shadow: 0 0 0.6rem #b2f3f2, 0 0 1.5rem #75f1f1,
+ -0.2rem 0.1rem 1rem #75f1f1, 0.2rem 0.1rem 1rem #75f1f1,
+ 0 -0.5rem 2rem #1cf3f1, 0 0.5rem 3rem #1cf3f1;
+ }
+ 28%,
+ 33% {
+ color: #75f1f1;
+ text-shadow: 0 0 0.6rem #b2f3f2, 0 0 1.5rem #75f1f1;
+ }
+ 82%,
+ 97% {
+ color: #178685;
+ text-shadow: none;
+ }
+}
+
+@keyframes flicker {
+ from {
+ opacity: 1;
+ }
+
+ 4% {
+ opacity: 0.9;
+ }
+
+ 6% {
+ opacity: 0.85;
+ }
+
+ 8% {
+ opacity: 0.95;
+ }
+
+ 10% {
+ opacity: 0.9;
+ }
+
+ 11% {
+ opacity: 0.922;
+ }
+
+ 12% {
+ opacity: 0.9;
+ }
+
+ 14% {
+ opacity: 0.95;
+ }
+
+ 16% {
+ opacity: 0.98;
+ }
+
+ 17% {
+ opacity: 0.9;
+ }
+
+ 19% {
+ opacity: 0.93;
+ }
+
+ 20% {
+ opacity: 0.99;
+ }
+
+ 24% {
+ opacity: 1;
+ }
+
+ 26% {
+ opacity: 0.94;
+ }
+
+ 28% {
+ opacity: 0.98;
+ }
+
+ 37% {
+ opacity: 0.93;
+ }
+
+ 38% {
+ opacity: 0.5;
+ }
+
+ 39% {
+ opacity: 0.96;
+ }
+
+ 42% {
+ opacity: 1;
+ }
+
+ 44% {
+ opacity: 0.97;
+ }
+
+ 46% {
+ opacity: 0.94;
+ }
+
+ 56% {
+ opacity: 0.9;
+ }
+
+ 58% {
+ opacity: 0.9;
+ }
+
+ 60% {
+ opacity: 0.99;
+ }
+
+ 68% {
+ opacity: 1;
+ }
+
+ 70% {
+ opacity: 0.9;
+ }
+
+ 72% {
+ opacity: 0.95;
+ }
+
+ 93% {
+ opacity: 0.93;
+ }
+
+ 95% {
+ opacity: 0.95;
+ }
+
+ 97% {
+ opacity: 0.93;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+/*TODO: text input background colors*/
+/*.autocomplete_tags {
+ background-color: #fff8dc;
+}*/
+
+ul.ui-autocomplete {
+ background: #383838;
+ border: solid 2px #ff6499;
+ border-radius: 4px;
+}
+
+ul.ui-autocomplete, ul.ui-autocomplete > li {
+ max-width: 60ch;
+ line-height: 1.5;
+ padding-left: 5px;
+}
+
+ul.ui-autocomplete > li:nth-child(odd) {
+ background: #000000;
+}
+
+ul.ui-autocomplete > li:nth-child(even) {
+ background: #383838;
+}
+
+.noleft{
+padding-left:2rem;
+}
+HEADER {
+margin-bottom:0.9rem;
+}
+HEADER #site-title {
+padding:0.6rem 2rem 0.25rem;
+}
+HEADER ul#navbar, HEADER ul#subnavbar {
+font-family:Verdana,Helvetica,sans-serif;
+font-size:110%;
+}
+HEADER ul#navbar {
+margin:0;
+padding:0 1rem 0 2rem;
+}
+HEADER ul#navbar li {
+margin:0;
+}
+HEADER ul#navbar li a {
+display:inline-block;
+margin:0 0.15rem;
+padding:0.4rem 0.6rem;
+}
+HEADER ul#navbar li:first-child a {
+margin-left: -0.6rem;
+color: #FF3333;
+font-weight: bold;
+}
+HEADER ul#navbar li a.current-page {
+background-color:#383838;
+border-radius:0.2rem 0.2rem 0 0;
+font-weight:bold;
+}
+HEADER ul#subnavbar {
+margin:0 0 0.5rem;
+padding:0 1rem 0 2rem;
+background-color:#383838;
+}
+HEADER ul#subnavbar li {
+display:inline-block;
+margin:0 0.15rem;
+padding:0.4rem 0.6rem;
+}
+HEADER ul#subnavbar li:first-child {
+margin-left: -0.6rem;
+}
+body {
+background-color:#000000;
+color:#FFFFFF;
+font-weight:normal;
+font-style:normal;
+font-variant:normal;
+font-size-adjust:none;
+font-stretch:normal;
+font-size:80%;
+line-height:normal;
+-x-system-font:none;
+}
+h1 {
+margin-top:0;
+margin-bottom:0;
+padding:0.3rem;
+font-size:2.2rem;
+}
+h1 a {
+color:black;
+}
+h3 {
+margin-top:0;
+margin-bottom:0;
+padding:0.2rem 0.2rem 0.2rem 0;
+font-size:1rem;
+}
+h4 {
+font-size:1.4rem;
+}
+h5 {
+font-size:1.2rem;
+}
+table.zebra {border-spacing: 0;border-collapse: collapse;}
+table.zebra > tbody > tr:hover {background: #383838;}
+table.zebra th { padding-right: 0.4rem;color: #171BB3;}
+table.zebra td {margin: 0;padding-right: 0.6rem;border: 1px dotted #EEE;}
+table.zebra th {margin: 0;text-align: left;}
+thead {
+font-weight:bold;
+-moz-background-clip:border;
+-moz-background-inline-policy:continuous;
+-moz-background-origin:padding;
+}
+td {
+vertical-align:top;
+}
+#subtitle {
+margin:auto;
+width:256px;
+border-top:medium none;
+text-align:center;
+font-size:0.75em;
+}
+#short-wiki-description {
+padding:0 2em;
+font-size:1.2em;
+}
+#short-wiki-description h2 {
+padding-bottom:0.2em;
+}
+FOOTER {
+clear:both;
+border-top:solid 1px #E7E7F7;
+margin-top:1rem;
+text-align:center;
+color:#555555;
+font-size:0.8rem;
+}
+FOOTER > DIV {
+margin: 1rem 2rem;
+}
+form {
+margin:0;
+}
+a {
+text-decoration:none;
+}
+a:hover {
+text-decoration:underline;
+}
+NAV {
+float:left;
+padding:0 1rem 0.2rem 2rem;
+width:11.5rem;
+text-align:left;
+}
+NAV section + section {
+margin-top:1rem;
+}
+NAV table {
+width:15rem;
+}
+NAV td {
+vertical-align:middle;
+}
+NAV input {
+padding:0;
+width:100%;
+}
+NAV select {
+padding:0;
+width:100%;
+}
+NAV h3 {
+text-align:left;
+}
+#comments p {
+overflow:hidden;
+max-width:150px;
+width:15rem;
+text-align:left;
+}
+TABLE.tag_list {
+ width: auto;
+ border-collapse: collapse;
+}
+TABLE.tag_list>THEAD {
+ display: none;
+}
+TABLE.tag_list>TBODY>TR>TD {
+ display: inline;
+ padding: 0;
+ line-height: 1em;
+}
+TABLE.tag_list>TBODY>TR>TD:after {
+ content: " ";
+}
+.tag_count {
+display:inline-block;
+margin-left:0.4rem;
+color:#AAAAAA;
+}
+.more {
+content:"More â";
+}
+.comment {
+margin-bottom:8px;
+}
+.comment .meta {
+width: 15rem;
+color: gray;
+}
+.comment TD {
+text-align: left;
+}
+.withleft {
+margin-left:14.5rem;
+}
+div#paginator {
+display:block;
+clear:both;
+padding:2em 0 1em;
+text-align:center;
+font-weight:bold;
+font-size:1em;
+}
+.paginator {
+margin:16px;
+text-align:center;
+}
+div#paginator b {
+margin:3px;
+padding:4px 8px;
+}
+div#paginator a {
+margin:3px;
+padding:4px 8px;
+border:1px solid #EEEEEE;
+}
+div#paginator a:hover {
+border:1px solid #EEEEEE;
+background:blue none repeat scroll 0 0;
+color:white;
+-moz-background-clip:border;
+-moz-background-inline-policy:continuous;
+-moz-background-origin:padding;
+}
+span.thumb {
+display:inline-block;
+float:left;
+width:220px;
+height:220px;
+text-align:center;
+}
+#pagelist {
+margin-top:32px;
+}
+#large_upload_form {
+width:600px;
+}
+.setupblock, .tagcategoryblock {
+margin:0.6rem 1rem 0.6rem 0;
+padding:0.5rem 0.6rem 0.7rem;
+width:18rem;
+border:1px solid #AAAAAA;
+border-radius:0.25rem;
+display:inline-block;
+}
+.tagcategoryblock table {
+width:100%;
+border-spacing:0;
+}
+.tagcategoryblock input, .tagcategoryblock span {
+width:100%;
+height:100%;
+}
+.tagcategoryblock td:first-child {
+padding:0.3rem 0.7rem 0.4rem 0;
+text-align:right;
+width:40%;
+}
+.tagcategoryblock td:last-child {
+width:60%;
+}
+.tagcategoryblock td:last-child span {
+padding:0.24rem 0.7rem 0.5rem 0;
+display:block;
+}
+.tagcategoryblock button {
+width:100%;
+margin-top:0.4rem;
+padding:0.2rem 0.6rem;
+}
+.helpable {
+border-bottom:1px dashed gray;
+}
+.ok {
+background:#AAFFAA none repeat scroll 0 0;
+-moz-background-clip:border;
+-moz-background-inline-policy:continuous;
+-moz-background-origin:padding;
+}
+.bad {
+background:#FFAAAA none repeat scroll 0 0;
+-moz-background-clip:border;
+-moz-background-inline-policy:continuous;
+-moz-background-origin:padding;
+}
+.comment .username {
+font-weight:bold;
+font-size:1.5em;
+}
+HEADER {
+text-align:left;
+}
+HEADER h1 {
+text-align:left;
+}
+* {
+margin:0;
+padding:0;
+font-family:Tahoma,Verdana,Helvetica,sans-serif;
+}
+a:link {
+color:#5becff;
+text-decoration:none;
+}
+a:visited {
+color:#ff6499;
+text-decoration:none;
+}
+a:hover {
+color:#ff6499;
+text-decoration:underline;
+}
+a:active {
+color:#ff6499;
+text-decoration:none;
+}
+ul.flat-list {
+display:block;
+margin:0;
+padding:0;
+}
+ul.flat-list * {
+display:inline;
+text-align:left;
+}
+ul.flat-list li {
+margin:0 1.3em 0 0;
+list-style-type:none;
+text-align:left;
+font-weight:bold;
+}
+ul.flat-list li a {
+font-weight:normal;
+}
+#tips {
+margin-left:16px;
+}
+#blotter1 {
+position: relative;
+margin-right:16px;
+margin-left:16px;
+font-size: 90%;
+}
+#blotter2 {
+margin-right:16px;
+margin-left:16px;
+font-size: 90%;
+}
+#flash {
+background:#383838;
+border:1px solid #e06d7f;
+margin:1rem 0;
+padding:1rem;
+text-align:center;
+border-radius:0.5rem;
+}
+ARTICLE {
+margin-right:1rem;
+}
+ARTICLE section + section {
+margin-top:1rem;
+}
+form + form {
+margin-top:0.5rem;
+}
+#Imagemain h3 {
+display:none;
+}
diff --git a/themes/okebooru/tag_list.theme.php b/themes/okebooru/tag_list.theme.php
new file mode 100644
index 00000000..31e174b8
--- /dev/null
+++ b/themes/okebooru/tag_list.theme.php
@@ -0,0 +1,10 @@
+disable_left();
+ parent::display_page($page);
+ }
+}
diff --git a/themes/okebooru/themelet.class.php b/themes/okebooru/themelet.class.php
new file mode 100644
index 00000000..927d0c87
--- /dev/null
+++ b/themes/okebooru/themelet.class.php
@@ -0,0 +1,66 @@
+build_paginator($page_number, $total_pages, $base, $query);
+ $page->add_block(new Block(null, $body, "main", 90));
+ }
+
+ private function gen_page_link(string $base_url, ?string $query, int $page, string $name): string
+ {
+ $link = make_link("$base_url/$page", $query);
+ return "$name ";
+ }
+
+ private function gen_page_link_block(string $base_url, ?string $query, int $page, int $current_page, string $name): string
+ {
+ $paginator = "";
+ if ($page == $current_page) {
+ $paginator .= "$page ";
+ } else {
+ $paginator .= $this->gen_page_link($base_url, $query, $page, $name);
+ }
+ return $paginator;
+ }
+
+ private function build_paginator(int $current_page, int $total_pages, string $base_url, ?string $query): string
+ {
+ $next = $current_page + 1;
+ $prev = $current_page - 1;
+
+ $at_start = ($current_page <= 3 || $total_pages <= 3);
+ $at_end = ($current_page >= $total_pages -2);
+
+ $first_html = $at_start ? "" : $this->gen_page_link($base_url, $query, 1, "1");
+ $prev_html = $at_start ? "" : $this->gen_page_link($base_url, $query, $prev, "<<");
+ $next_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $next, ">>");
+ $last_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $total_pages, "$total_pages");
+
+ $start = $current_page-2 > 1 ? $current_page-2 : 1;
+ $end = $current_page+2 <= $total_pages ? $current_page+2 : $total_pages;
+
+ $pages = [];
+ foreach (range($start, $end) as $i) {
+ $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, (string)$i);
+ }
+ $pages_html = implode(" ", $pages);
+
+ if (strlen($first_html) > 0) {
+ $pdots = "...";
+ } else {
+ $pdots = "";
+ }
+
+ if (strlen($last_html) > 0) {
+ $ndots = "...";
+ } else {
+ $ndots = "";
+ }
+
+ return "$prev_html $first_html $pdots $pages_html $ndots $last_html $next_html
";
+ }
+}
diff --git a/themes/okebooru/upload.theme.php b/themes/okebooru/upload.theme.php
new file mode 100644
index 00000000..31ce245e
--- /dev/null
+++ b/themes/okebooru/upload.theme.php
@@ -0,0 +1,16 @@
+add_block(new Block("Upload", $this->build_upload_block(), "left", 20));
+ }
+
+ public function display_page(Page $page)
+ {
+ $page->disable_left();
+ parent::display_page($page);
+ }
+}
diff --git a/themes/okebooru/user.theme.php b/themes/okebooru/user.theme.php
new file mode 100644
index 00000000..406dd73e
--- /dev/null
+++ b/themes/okebooru/user.theme.php
@@ -0,0 +1,115 @@
+set_title("Login");
+ $page->set_heading("Login");
+ $page->disable_left();
+ $html = "
+
+ ";
+ if ($config->get_bool("login_signup_enabled")) {
+ $html .= "Create Account ";
+ }
+ $page->add_block(new Block("Login", $html, "main", 90));
+ }
+
+ public function display_user_links(Page $page, User $user, $parts)
+ {
+ // no block in this theme
+ }
+ public function display_login_block(Page $page)
+ {
+ // no block in this theme
+ }
+
+ public function display_user_block(Page $page, User $user, $parts)
+ {
+ $html = "";
+ $blocked = ["Pools", "Pool Changes", "Alias Editor", "My Profile"];
+ foreach ($parts as $part) {
+ if (in_array($part["name"], $blocked)) {
+ continue;
+ }
+ $html .= "{$part["name"]} ";
+ }
+ $b = new Block("User Links", $html, "user", 90);
+ $b->is_content = false;
+ $page->add_block($b);
+ }
+
+ public function display_signup_page(Page $page)
+ {
+ global $config;
+ $tac = $config->get_string("login_tac", "");
+
+ $tfe = new TextFormattingEvent($tac);
+ send_event($tfe);
+ $tac = $tfe->formatted;
+
+ $reca = "".captcha_get_html()." ";
+
+ if (empty($tac)) {
+ $html = "";
+ } else {
+ $html = "$tac
";
+ }
+
+ $html .= "
+
+ ";
+
+ $page->set_title("Create Account");
+ $page->set_heading("Create Account");
+ $page->disable_left();
+ $page->add_block(new Block("Signup", $html));
+ }
+
+ public function display_ip_list(Page $page, array $uploads, array $comments, array $events)
+ {
+ $html = "";
+ $html .= "Uploaded from: ";
+ foreach ($uploads as $ip => $count) {
+ $html .= " $ip ($count)";
+ }
+ $html .= " Commented from:";
+ foreach ($comments as $ip => $count) {
+ $html .= " $ip ($count)";
+ }
+ $html .= " ";
+ $html .= "(Most recent at top)
";
+
+ $page->add_block(new Block("IPs", $html));
+ }
+
+ public function display_user_page(User $duser, $stats)
+ {
+ global $page;
+ $page->disable_left();
+ parent::display_user_page($duser, $stats);
+ }
+}
diff --git a/themes/okebooru/view.theme.php b/themes/okebooru/view.theme.php
new file mode 100644
index 00000000..421fece6
--- /dev/null
+++ b/themes/okebooru/view.theme.php
@@ -0,0 +1,77 @@
+set_heading(html_escape($image->get_tag_list()));
+ $page->add_block(new Block("Search", $this->build_navigation($image), "left", 0));
+ $page->add_block(new Block("Information", $this->build_information($image), "left", 15));
+ $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 15));
+ }
+
+ private function build_information(Image $image): string
+ {
+ $h_owner = html_escape($image->get_owner()->name);
+ $h_ownerlink = "$h_owner ";
+ $h_ip = html_escape($image->owner_ip);
+ $h_type = html_escape($image->get_mime());
+ $h_date = autodate($image->posted);
+ $h_filesize = to_shorthand_int($image->filesize);
+
+ global $user;
+ if ($user->can(Permissions::VIEW_IP)) {
+ $h_ownerlink .= " ($h_ip)";
+ }
+
+ $html = "
+ ID: {$image->id}
+ Uploader: $h_ownerlink
+ Date: $h_date
+ Size: $h_filesize ({$image->width}x{$image->height})
+ Type: $h_type
+ ";
+
+ if ($image->length!=null) {
+ $h_length = format_milliseconds($image->length);
+ $html .= " Length: $h_length";
+ }
+
+
+ if (!is_null($image->source)) {
+ $h_source = html_escape($image->source);
+ if (substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") {
+ $h_source = "http://" . $h_source;
+ }
+ $html .= " Source: link ";
+ }
+
+ if (Extension::is_enabled(RatingsInfo::KEY)) {
+ if ($image->rating == null || $image->rating == "?") {
+ $image->rating = "?";
+ }
+ if (Extension::is_enabled(RatingsInfo::KEY)) {
+ $h_rating = Ratings::rating_to_human($image->rating);
+ $html .= " Rating: $h_rating";
+ }
+ }
+
+ return $html;
+ }
+
+ protected function build_navigation(Image $image): string
+ {
+ //$h_pin = $this->build_pin($image);
+ $h_search = "
+
+ ";
+
+ return "$h_search";
+ }
+}