From f6973fd01f7ee4282c100e0d2d67115b4881b12a Mon Sep 17 00:00:00 2001 From: Shish Date: Sat, 27 Apr 2024 01:09:41 +0100 Subject: [PATCH 001/101] [core] make PageRequest->page_starts_with be less weird --- core/event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/event.php b/core/event.php index 5b545eed0..814a1bee0 100644 --- a/core/event.php +++ b/core/event.php @@ -167,7 +167,7 @@ public function req_POST_array(string $key): array public function page_starts_with(string $name): bool { - return (count($this->args) >= 1) && ($this->args[0] == $name); + return str_starts_with($this->path, $name); } /** From 2fe44303c3b2a4c566644aeee3a78b0c68aefede Mon Sep 17 00:00:00 2001 From: Shish Date: Sat, 4 May 2024 14:52:01 +0100 Subject: [PATCH 002/101] [dev] postStartCommand rather than postCreateCommand for running the service --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fb1ad12f3..4d964d6a8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,7 +23,7 @@ }, "updateContentCommand": "composer install && cp ./.devcontainer/bash_history /root/.bash_history", - "postCreateCommand": "./.docker/entrypoint.sh php ./.docker/run.php", + "postStartCommand": "./.docker/entrypoint.sh php ./.docker/run.php", "containerEnv": { "UID": "2000", "GID": "2000", From 8b674d598e37420cd4a9d5c332c17a2e27e36268 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Sun, 28 Apr 2024 12:04:00 +0000 Subject: [PATCH 003/101] [filter] fix thumb display css unsetting the display option can disable display: block, which allows the thumbnails to be centred in their container --- ext/filter/style.css | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/filter/style.css b/ext/filter/style.css index ead4ca372..dc8887c8e 100644 --- a/ext/filter/style.css +++ b/ext/filter/style.css @@ -1,4 +1,3 @@ #filter-list{padding:revert; text-align:left;} -.thumb.filtered{display:unset} .thumb.filtered.filtered-active{display:none;} .filter-inactive,.filter-inactive:hover{text-decoration: line-through;} \ No newline at end of file From ba2bad48a66c13b94e39ddf15b07fa7f0c704e88 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 26 Apr 2024 22:35:48 +0000 Subject: [PATCH 004/101] [user] fix typo in password check --- ext/user/main.php | 2 +- ext/user/test.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/user/main.php b/ext/user/main.php index 8bec2cf16..ec67f8fdf 100644 --- a/ext/user/main.php +++ b/ext/user/main.php @@ -210,7 +210,7 @@ public function onPageRequest(PageRequestEvent $event): void new UserCreationEvent( $event->req_POST("name"), $event->req_POST("pass1"), - $event->req_POST("pass1"), + $event->req_POST("pass2"), $event->req_POST("email"), false ) diff --git a/ext/user/test.php b/ext/user/test.php index cd1df1b6e..be275669b 100644 --- a/ext/user/test.php +++ b/ext/user/test.php @@ -62,6 +62,7 @@ public function testCreateOther(): void $this->post_page('user_admin/create_other', [ 'name' => 'testnew', 'pass1' => 'testnew', + 'pass2' => 'testnew', 'email' => '', ]); }); @@ -71,6 +72,7 @@ public function testCreateOther(): void $this->post_page('user_admin/create_other', [ 'name' => 'testnew', 'pass1' => 'testnew', + 'pass2' => 'testnew', 'email' => '', ]); $this->assertEquals(302, $page->code); From e23e822dd6fe9db16455e52a491bc01b6bcf05d2 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 3 May 2024 01:19:36 +0000 Subject: [PATCH 005/101] [statistics] improve accuracy of tagger statistic --- ext/statistics/main.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ext/statistics/main.php b/ext/statistics/main.php index 901a354b5..18d564799 100644 --- a/ext/statistics/main.php +++ b/ext/statistics/main.php @@ -91,13 +91,13 @@ public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void private function get_tag_stats(int $anon_id): array { global $database; - // Returns the username and tags from each tag history entry. Excludes Anonymous - $tag_stats = $database->get_all("SELECT users.name,tag_histories.tags,tag_histories.image_id FROM tag_histories INNER JOIN users ON users.id = tag_histories.user_id WHERE tag_histories.user_id <> $anon_id;"); + // Returns the username and tags from each tag history entry. This includes Anonymous tag histories to prevent their tagging being ignored and credited to the next user to edit. + $tag_stats = $database->get_all("SELECT users.id,users.name,tag_histories.tags,tag_histories.image_id FROM tag_histories INNER JOIN users ON users.id = tag_histories.user_id WHERE 1=1;"); // Group tag history entries by image id $tag_histories = []; foreach ($tag_stats as $ts) { - $tag_history = ['name' => $ts['name'], 'tags' => $ts['tags']]; + $tag_history = ['uid' => $ts['id'], 'name' => $ts['name'], 'tags' => $ts['tags']]; $id = $ts['image_id']; array_key_exists($id, $tag_histories) ? array_push($tag_histories[$id], $tag_history) : $tag_histories[$id] = [$tag_history]; } @@ -108,8 +108,10 @@ private function get_tag_stats(int $anon_id): array $prev = []; foreach ($image as $change) { $curr = explode(' ', $change['tags']); - $name = (string)$change['name']; - $tag_tally[$name] += count(array_diff($curr, $prev)); + if ($change['uid'] != $anon_id) { + $name = (string)$change['name']; + $tag_tally[$name] += count(array_diff($curr, $prev)); + } $prev = $curr; } } From 7b682bf246245f92fd059feae6e84bc373f90ade Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 3 May 2024 02:19:05 +0000 Subject: [PATCH 006/101] [statistics] remove unused variable --- ext/statistics/main.php | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/statistics/main.php b/ext/statistics/main.php index 18d564799..cfb778474 100644 --- a/ext/statistics/main.php +++ b/ext/statistics/main.php @@ -104,7 +104,6 @@ private function get_tag_stats(int $anon_id): array // Count changes made in each tag history and tally tags for users $tag_tally = []; foreach ($tag_histories as $i => $image) { - $first = true; $prev = []; foreach ($image as $change) { $curr = explode(' ', $change['tags']); From 9453fda166cd1d5916d9e629ed002a61183596f9 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 3 May 2024 03:00:04 +0000 Subject: [PATCH 007/101] [statistics] omit banned users --- ext/statistics/main.php | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/ext/statistics/main.php b/ext/statistics/main.php index cfb778474..029615bdf 100644 --- a/ext/statistics/main.php +++ b/ext/statistics/main.php @@ -8,6 +8,8 @@ class Statistics extends Extension { /** @var StatisticsTheme */ protected Themelet $theme; + /** @var String[] */ + private array $unlisted = ['anonymous', 'ghost', 'hellbanned']; public function onPageRequest(PageRequestEvent $event): void { @@ -16,7 +18,7 @@ public function onPageRequest(PageRequestEvent $event): void $base_href = get_base_href(); $sitename = $config->get_string(SetupConfig::TITLE); $theme_name = $config->get_string(SetupConfig::THEME); - $anon_id = $config->get_int("anon_id"); + $unlisted = "'".implode("','", $this->unlisted)."'"; $limit = 10; if ($event->page_matches("stats/100")) { @@ -24,7 +26,7 @@ public function onPageRequest(PageRequestEvent $event): void } if (Extension::is_enabled(TagHistoryInfo::KEY)) { - $tag_tally = $this->get_tag_stats($anon_id); + $tag_tally = $this->get_tag_stats($this->unlisted); arsort($tag_tally, $flags = SORT_NUMERIC); $tag_table = $this->theme->build_table($tag_tally, "Taggers", "Top $limit taggers", $limit); } else { @@ -32,7 +34,7 @@ public function onPageRequest(PageRequestEvent $event): void } $upload_tally = []; - foreach ($this->get_upload_stats($anon_id) as $name) { + foreach ($this->get_upload_stats($unlisted) as $name) { array_key_exists($name, $upload_tally) ? $upload_tally[$name] += 1 : $upload_tally[$name] = 1; } @@ -41,7 +43,7 @@ public function onPageRequest(PageRequestEvent $event): void if (Extension::is_enabled(CommentListInfo::KEY)) { $comment_tally = []; - foreach ($this->get_comment_stats($anon_id) as $name) { + foreach ($this->get_comment_stats($unlisted) as $name) { array_key_exists($name, $comment_tally) ? $comment_tally[$name] += 1 : $comment_tally[$name] = 1; } @@ -53,7 +55,7 @@ public function onPageRequest(PageRequestEvent $event): void if (Extension::is_enabled(FavoritesInfo::KEY)) { $favorite_tally = []; - foreach ($this->get_favorite_stats($anon_id) as $name) { + foreach ($this->get_favorite_stats($unlisted) as $name) { array_key_exists($name, $favorite_tally) ? $favorite_tally[$name] += 1 : $favorite_tally[$name] = 1; } @@ -86,18 +88,19 @@ public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void } /** + * @param String[] $unlisted * @return array */ - private function get_tag_stats(int $anon_id): array + private function get_tag_stats(array $unlisted): array { global $database; // Returns the username and tags from each tag history entry. This includes Anonymous tag histories to prevent their tagging being ignored and credited to the next user to edit. - $tag_stats = $database->get_all("SELECT users.id,users.name,tag_histories.tags,tag_histories.image_id FROM tag_histories INNER JOIN users ON users.id = tag_histories.user_id WHERE 1=1;"); + $tag_stats = $database->get_all("SELECT users.class,users.name,tag_histories.tags,tag_histories.image_id FROM tag_histories INNER JOIN users ON users.id = tag_histories.user_id WHERE 1=1 ORDER BY users.id;"); // Group tag history entries by image id $tag_histories = []; foreach ($tag_stats as $ts) { - $tag_history = ['uid' => $ts['id'], 'name' => $ts['name'], 'tags' => $ts['tags']]; + $tag_history = ['class' => $ts['class'], 'name' => $ts['name'], 'tags' => $ts['tags']]; $id = $ts['image_id']; array_key_exists($id, $tag_histories) ? array_push($tag_histories[$id], $tag_history) : $tag_histories[$id] = [$tag_history]; } @@ -107,7 +110,7 @@ private function get_tag_stats(int $anon_id): array $prev = []; foreach ($image as $change) { $curr = explode(' ', $change['tags']); - if ($change['uid'] != $anon_id) { + if (!in_array($change['class'], $unlisted)) { $name = (string)$change['name']; $tag_tally[$name] += count(array_diff($curr, $prev)); } @@ -120,30 +123,30 @@ private function get_tag_stats(int $anon_id): array /** * @return array */ - private function get_upload_stats(int $anon_id): array + private function get_upload_stats(string $unlisted): array { global $database; - // Returns the username of each post, as an array. Excludes Anonymous - return $database->get_col("SELECT users.name FROM images INNER JOIN users ON users.id = images.owner_id WHERE images.owner_id <> $anon_id;"); + // Returns the username of each post, as an array. + return $database->get_col("SELECT users.name FROM images INNER JOIN users ON users.id = images.owner_id WHERE users.class NOT IN ($unlisted) ORDER BY users.id;"); } /** * @return array */ - private function get_comment_stats(int $anon_id): array + private function get_comment_stats(string $unlisted): array { global $database; - // Returns the username of each comment, as an array. Excludes Anonymous - return $database->get_col("SELECT users.name FROM comments INNER JOIN users ON users.id = comments.owner_id WHERE comments.owner_id <> $anon_id;"); + // Returns the username of each comment, as an array. + return $database->get_col("SELECT users.name FROM comments INNER JOIN users ON users.id = comments.owner_id WHERE users.class NOT IN ($unlisted) ORDER BY users.id;"); } /** * @return array */ - private function get_favorite_stats(int $anon_id): array + private function get_favorite_stats(string $unlisted): array { global $database; - // Returns the username of each favorite, as an array. Excludes Anonymous - return $database->get_col("SELECT users.name FROM user_favorites INNER JOIN users ON users.id = user_favorites.user_id WHERE user_favorites.user_id <> $anon_id;"); + // Returns the username of each favorite, as an array. + return $database->get_col("SELECT users.name FROM user_favorites INNER JOIN users ON users.id = user_favorites.user_id WHERE users.class NOT IN ($unlisted) ORDER BY users.id;"); } } From 5cbbe5e1b3e1e8bb466a5775a5b0918c34060463 Mon Sep 17 00:00:00 2001 From: Shish Date: Sat, 4 May 2024 15:43:29 +0100 Subject: [PATCH 008/101] [core] remove is_logged_in This was only used in a couple of places, and user classes are more useful --- core/user.php | 6 ------ ext/bulk_actions/main.php | 18 ++++++++---------- ext/pools/main.php | 12 +++++++----- ext/transcode/main.php | 3 +-- ext/user/main.php | 5 ++++- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/core/user.php b/core/user.php index ebfc85a36..d415b48a8 100644 --- a/core/user.php +++ b/core/user.php @@ -171,12 +171,6 @@ public function is_anonymous(): bool return ($this->id === $config->get_int('anon_id')); } - public function is_logged_in(): bool - { - global $config; - return ($this->id !== $config->get_int('anon_id')); - } - public function set_class(string $class): void { global $database; diff --git a/ext/bulk_actions/main.php b/ext/bulk_actions/main.php index 11b68fafb..7d298664a 100644 --- a/ext/bulk_actions/main.php +++ b/ext/bulk_actions/main.php @@ -68,20 +68,18 @@ public function onPostListBuilding(PostListBuildingEvent $event): void { global $page, $user; - if ($user->is_logged_in()) { - $babbe = new BulkActionBlockBuildingEvent(); - $babbe->search_terms = $event->search_terms; + $babbe = new BulkActionBlockBuildingEvent(); + $babbe->search_terms = $event->search_terms; - send_event($babbe); + send_event($babbe); - if (sizeof($babbe->actions) == 0) { - return; - } + if (sizeof($babbe->actions) == 0) { + return; + } - usort($babbe->actions, [$this, "sort_blocks"]); + usort($babbe->actions, [$this, "sort_blocks"]); - $this->theme->display_selector($page, $babbe->actions, Tag::implode($event->search_terms)); - } + $this->theme->display_selector($page, $babbe->actions, Tag::implode($event->search_terms)); } public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event): void diff --git a/ext/pools/main.php b/ext/pools/main.php index 6ff101357..9bad4294e 100644 --- a/ext/pools/main.php +++ b/ext/pools/main.php @@ -551,13 +551,15 @@ public function onTagTermParse(TagTermParseEvent $event): void public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event): void { - global $database; + global $database, $user; - $options = $database->get_pairs("SELECT id,title FROM pools ORDER BY title"); + if(!$user->can(Permissions::POOLS_UPDATE)) { + $options = $database->get_pairs("SELECT id,title FROM pools ORDER BY title"); - // TODO: Don't cast into strings, make BABBE accept HTMLElement instead. - $event->add_action("bulk_pool_add_existing", "Add To (P)ool", "p", "", (string) $this->theme->get_bulk_pool_selector($options)); - $event->add_action("bulk_pool_add_new", "Create Pool", "", "", (string) $this->theme->get_bulk_pool_input($event->search_terms)); + // TODO: Don't cast into strings, make BABBE accept HTMLElement instead. + $event->add_action("bulk_pool_add_existing", "Add To (P)ool", "p", "", (string) $this->theme->get_bulk_pool_selector($options)); + $event->add_action("bulk_pool_add_new", "Create Pool", "", "", (string) $this->theme->get_bulk_pool_input($event->search_terms)); + } } public function onBulkAction(BulkActionEvent $event): void diff --git a/ext/transcode/main.php b/ext/transcode/main.php index 068aa9838..025f58f88 100644 --- a/ext/transcode/main.php +++ b/ext/transcode/main.php @@ -260,9 +260,8 @@ public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event): { global $user, $config; - $engine = $config->get_string(TranscodeConfig::ENGINE); - if ($user->can(Permissions::EDIT_FILES)) { + $engine = $config->get_string(TranscodeConfig::ENGINE); $event->add_action(self::ACTION_BULK_TRANSCODE, "Transcode Image", null, "", $this->theme->get_transcode_picker_html($this->get_supported_output_mimes($engine))); } } diff --git a/ext/user/main.php b/ext/user/main.php index ec67f8fdf..eff8d1c59 100644 --- a/ext/user/main.php +++ b/ext/user/main.php @@ -393,7 +393,10 @@ private function display_stats(UserPageBuildingEvent $event): void $this->theme->display_user_links($page, $user, $ubbe->get_parts()); } if ( - ($user->can(Permissions::VIEW_IP) || ($user->is_logged_in() && $user->id == $event->display_user->id)) && # admin or self-user + ( + $user->can(Permissions::VIEW_IP) || # user can view all IPS + ($user->id == $event->display_user->id) # or user is viewing themselves + ) && ($event->display_user->id != $config->get_int('anon_id')) # don't show anon's IP list, it is le huge ) { $this->theme->display_ip_list( From baf55a26fa137c8694dbe61caa8e260f809b5a2e Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:08:51 +0000 Subject: [PATCH 009/101] [terms] add terms and conditions gate --- core/testcase.php | 1 + ext/terms/info.php | 16 ++++++++++++++++ ext/terms/main.php | 40 ++++++++++++++++++++++++++++++++++++++++ ext/terms/theme.php | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 ext/terms/info.php create mode 100644 ext/terms/main.php create mode 100644 ext/terms/theme.php diff --git a/core/testcase.php b/core/testcase.php index 839c6f63c..b49eec030 100644 --- a/core/testcase.php +++ b/core/testcase.php @@ -110,6 +110,7 @@ protected static function request( $_SERVER['REQUEST_URI'] = make_link($page_name, http_build_query($get_args)); $_GET = $get_args; $_POST = $post_args; + $_COOKIE['shm_accepted_terms'] = "true"; $page = new Page(); send_event(new PageRequestEvent($method, $page_name, $get_args, $post_args)); if ($page->mode == PageMode::REDIRECT) { diff --git a/ext/terms/info.php b/ext/terms/info.php new file mode 100644 index 000000000..466d25df7 --- /dev/null +++ b/ext/terms/info.php @@ -0,0 +1,16 @@ + ""]; + public string $license = "GPLv2"; + public string $description = "Show a page of terms which must be accepted before continuing"; +} diff --git a/ext/terms/main.php b/ext/terms/main.php new file mode 100644 index 000000000..14c30bfce --- /dev/null +++ b/ext/terms/main.php @@ -0,0 +1,40 @@ +set_default_string("terms_message", "Cookies may be used. Please read our [url=site://wiki/privacy]privacy policy[/url] for more information.\nBy accepting to enter you agree to our [url=site://wiki/rules]rules[/url] and [url=site://wiki/terms_of_service]terms of service[/url]."); + } + + public function onSetupBuilding(SetupBuildingEvent $event): void + { + $sb = $event->panel->create_new_block("Terms & Conditions Gate"); + $sb->add_longtext_option("terms_message", 'Message (Use BBCode)'); + } + + public function onPageRequest(PageRequestEvent $event): void + { + global $config, $page, $user; + if ($event->page_starts_with("accept_terms")) { + $page->add_cookie("accepted_terms", "true", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(make_link(explode('/', $event->path, 2)[1])); + } else { + // run on all pages unless logged in or cookie exists + if ($user->is_anonymous() && !isset($_COOKIE[$config->get_string('cookie_prefix', 'shm') . '_' . 'accepted_terms'])) { + $sitename = $config->get_string(SetupConfig::TITLE); + $body = format_text($config->get_string("terms_message")); + $this->theme->display_page($page, $sitename, $event->path, $body); + } + } + } +} diff --git a/ext/terms/theme.php b/ext/terms/theme.php new file mode 100644 index 000000000..7708c4ccd --- /dev/null +++ b/ext/terms/theme.php @@ -0,0 +1,37 @@ +set_mode(PageMode::DATA); + $page->add_auto_html_headers(); + $hh = $page->get_all_html_headers(); + $page->set_data( + << + + + $sitename + + + $hh + + +
+

$sitename

+ $body +
+ +
+
+ + +EOD + ); + } +} From 15aaedb951973d1d51d7dfc4818489212adfa6f3 Mon Sep 17 00:00:00 2001 From: Shish Date: Wed, 5 Jun 2024 12:50:12 +0100 Subject: [PATCH 010/101] [danbooru2] minor fixes for signup form --- themes/danbooru2/user.theme.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/themes/danbooru2/user.theme.php b/themes/danbooru2/user.theme.php index 3772db162..6dd1b0cc8 100644 --- a/themes/danbooru2/user.theme.php +++ b/themes/danbooru2/user.theme.php @@ -65,13 +65,19 @@ public function display_user_block(Page $page, User $user, array $parts): void public function display_signup_page(Page $page): void { - global $config; + global $config, $user; $tac = $config->get_string("login_tac", ""); $tac = send_event(new TextFormattingEvent($tac))->formatted; $reca = "".captcha_get_html().""; + $email_required = ( + $config->get_bool("user_email_required") && + !$user->can(Permissions::CREATE_OTHER_USER) + ); + $email_text = $email_required ? "Email" : "Email (Optional)"; + if (empty($tac)) { $html = ""; } else { @@ -84,8 +90,8 @@ public function display_signup_page(Page $page): void Name Password Repeat Password - Email (Optional) - $reca; + $email_text + $reca From b6088f95c341e983573b29dd47c19db8a5b4fd15 Mon Sep 17 00:00:00 2001 From: Shish Date: Wed, 5 Jun 2024 13:39:51 +0100 Subject: [PATCH 011/101] [notes] avoid jiggling on _commit() by accounting for border widths --- ext/notes/script.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/notes/script.js b/ext/notes/script.js index 80ea8995d..94aec4468 100644 --- a/ext/notes/script.js +++ b/ext/notes/script.js @@ -88,7 +88,7 @@ function renderEditor(noteDiv, note) { dragStart = { x: e.pageX, y: e.pageY, - mode: getArea(e.offsetX, e.offsetY, noteDiv.offsetWidth, noteDiv.offsetHeight), + mode: getArea(e.offsetX, e.offsetY, noteDiv.clientWidth, noteDiv.clientHeight), }; noteDiv.classList.add("dragging"); }); @@ -113,7 +113,7 @@ function renderEditor(noteDiv, note) { noteDiv.style.width = (note.width * scale) + (e.pageX - dragStart.x) + 'px'; } } else { - let area = getArea(e.offsetX, e.offsetY, noteDiv.offsetWidth, noteDiv.offsetHeight); + let area = getArea(e.offsetX, e.offsetY, noteDiv.clientWidth, noteDiv.clientHeight); if(area == "c") { noteDiv.style.cursor = 'move'; } else { @@ -126,8 +126,8 @@ function renderEditor(noteDiv, note) { dragStart = null; note.x1 = Math.round(noteDiv.offsetLeft / scale); note.y1 = Math.round(noteDiv.offsetTop / scale); - note.width = Math.round(noteDiv.offsetWidth / scale); - note.height = Math.round(noteDiv.offsetHeight / scale); + note.width = Math.round(noteDiv.clientWidth / scale); + note.height = Math.round(noteDiv.clientHeight / scale); renderNotes(); } noteDiv.addEventListener('mouseup', _commit); From db148da479b335047018dcc18ce5d227175056ec Mon Sep 17 00:00:00 2001 From: Shish Date: Wed, 5 Jun 2024 13:58:59 +0100 Subject: [PATCH 012/101] [core] add shm_make_link JS function, to generate links from JS which work both with and without niceurls, fixes #1160, fixes #1151 --- core/basepage.php | 1 + ext/autocomplete/script.js | 2 +- ext/notes/script.js | 6 +++--- ext/static_files/init.js | 7 +++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/basepage.php b/core/basepage.php index b8ffffc95..9aa89091e 100644 --- a/core/basepage.php +++ b/core/basepage.php @@ -557,6 +557,7 @@ public function render(): void $body_attrs = [ "data-userclass" => $user->class->name, "data-base-href" => get_base_href(), + "data-base-link" => make_link(""), ]; print emptyHTML( diff --git a/ext/autocomplete/script.js b/ext/autocomplete/script.js index 910026ddd..289643e04 100644 --- a/ext/autocomplete/script.js +++ b/ext/autocomplete/script.js @@ -43,7 +43,7 @@ function updateCompletions(element) { else { element.completer_timeout = setTimeout(() => { const wordWithoutMinus = word.replace(/^-/, ''); - fetch((document.body.getAttribute("data-base-href") ?? "") + '/api/internal/autocomplete?s=' + wordWithoutMinus).then( + fetch(shm_make_link('api/internal/autocomplete', {s: wordWithoutMinus})).then( (response) => response.json() ).then((json) => { if(element.selected_completion !== -1) { diff --git a/ext/notes/script.js b/ext/notes/script.js index 94aec4468..9b4e79bf8 100644 --- a/ext/notes/script.js +++ b/ext/notes/script.js @@ -150,7 +150,7 @@ function renderEditor(noteDiv, note) { save.innerText = 'Save'; save.addEventListener('click', () => { if(note.note_id == null) { - fetch('/note/create_note', { + fetch(shm_make_link('note/create_note'), { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -169,7 +169,7 @@ function renderEditor(noteDiv, note) { alert(error); }); } else { - fetch('/note/update_note', { + fetch(shm_make_link('note/update_note'), { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -205,7 +205,7 @@ function renderEditor(noteDiv, note) { deleteNote.innerText = 'Delete'; deleteNote.addEventListener('click', () => { // TODO: delete note from server - fetch('/note/delete_note', { + fetch(shm_make_link('note/delete_note'), { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/ext/static_files/init.js b/ext/static_files/init.js index fe6cabf29..0a93530cd 100644 --- a/ext/static_files/init.js +++ b/ext/static_files/init.js @@ -4,6 +4,13 @@ function shm_cookie_set(name, value) { function shm_cookie_get(name) { return Cookies.get(name); } +function shm_make_link(page, query) { + let base = (document.body.getAttribute("data-base-link") ?? ""); + let joiner = base.indexOf("?") === -1 ? "?" : "&"; + let url = base + page; + if(query) url += joiner + new URLSearchParams(query).toString(); + return url; +} function shm_log(section, ...message) { window.dispatchEvent(new CustomEvent("shm_log", {detail: {section, message}})); From d04407d3bccde6e7e237a11bb79bbc74f23eaf58 Mon Sep 17 00:00:00 2001 From: Shish Date: Wed, 5 Jun 2024 14:04:47 +0100 Subject: [PATCH 013/101] bump `main` branch is working towards 2.12, not 2.11 --- core/sys_config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys_config.php b/core/sys_config.php index 2af3ac692..8c286d2c1 100644 --- a/core/sys_config.php +++ b/core/sys_config.php @@ -31,7 +31,7 @@ function _d(string $name, mixed $value): void _d("COOKIE_PREFIX", 'shm'); // string if you run multiple galleries with non-shared logins, give them different prefixes _d("SPEED_HAX", false); // boolean do some questionable things in the name of performance _d("WH_SPLITS", 1); // int how many levels of subfolders to put in the warehouse -_d("VERSION", "2.11.0-alpha"); // string shimmie version +_d("VERSION", "2.12.0-alpha"); // string shimmie version _d("TIMEZONE", null); // string timezone _d("EXTRA_EXTS", ""); // string optional extra extensions _d("BASE_HREF", null); // string force a specific base URL (default is auto-detect) From 68be2c7123c91616ad274a668821f6a204f0d7c1 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 7 Jun 2024 07:56:03 +0000 Subject: [PATCH 014/101] [terms] implement terms and conditions blur modal, fixes #1166 --- ext/terms/style.css | 19 +++++++++++++++++++ ext/terms/theme.php | 36 +++++++++++------------------------- 2 files changed, 30 insertions(+), 25 deletions(-) create mode 100644 ext/terms/style.css diff --git a/ext/terms/style.css b/ext/terms/style.css new file mode 100644 index 000000000..f70f7f50e --- /dev/null +++ b/ext/terms/style.css @@ -0,0 +1,19 @@ +.terms-modal-enter { + margin: 10px; +} +#terms-modal { + margin: auto; + margin-top: 20vh; + padding: 5px 20px; + text-align: center; + width: fit-content; +} +#terms-modal-bg { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999; + backdrop-filter: blur(10px); +} \ No newline at end of file diff --git a/ext/terms/theme.php b/ext/terms/theme.php index 7708c4ccd..4f592fde4 100644 --- a/ext/terms/theme.php +++ b/ext/terms/theme.php @@ -8,30 +8,16 @@ class TermsTheme extends Themelet { public function display_page(Page $page, string $sitename, string $path, string $body): void { - $page->set_mode(PageMode::DATA); - $page->add_auto_html_headers(); - $hh = $page->get_all_html_headers(); - $page->set_data( - << - - - $sitename - - - $hh - - -
-

$sitename

- $body -
- -
-
- - -EOD - ); + $html = + "
+ +

$sitename

+ $body +
+ +
+
+
"; + $page->add_block(new Block(null, $html, "main", 1)); } } From 1bb0be60c62e3a1ff909e082072a55015f39d766 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 31 May 2024 05:39:48 +0000 Subject: [PATCH 015/101] [handle_pixel] show zoom cursor on images --- ext/handle_pixel/script.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ext/handle_pixel/script.js b/ext/handle_pixel/script.js index dd738cf58..980e0bd0a 100644 --- a/ext/handle_pixel/script.js +++ b/ext/handle_pixel/script.js @@ -21,6 +21,17 @@ document.addEventListener('DOMContentLoaded', () => { img.css('max-height', (window.innerHeight * 0.95) + 'px'); } + const zoomed_height_diff = Math.round(window.innerHeight * 0.95 - img.height()); + const zoomed_width_diff = Math.round(img.parent().width() * 0.95 - img.width()); + + if (zoomed_height_diff > 0 && zoomed_width_diff > 0) { + img.css('cursor', ''); + } else if (zoom_type == "full") { + img.css('cursor', 'zoom-out'); + } else { + img.css('cursor', 'zoom-in'); + } + $(".shm-zoomer").val(zoom_type); if (save_cookie) { From 2f07d4c71cf9a6ef14805e2682566c18f3071d7f Mon Sep 17 00:00:00 2001 From: Shish Date: Fri, 7 Jun 2024 14:33:45 +0100 Subject: [PATCH 016/101] [core] make request cookies configurable --- core/testcase.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/testcase.php b/core/testcase.php index b49eec030..575b82dc5 100644 --- a/core/testcase.php +++ b/core/testcase.php @@ -91,12 +91,14 @@ private static function check_args(array $args): array /** * @param array $get_args * @param array $post_args + * @param array $cookies */ protected static function request( string $method, string $page_name, array $get_args = [], - array $post_args = [] + array $post_args = [], + array $cookies = ["shm_accepted_terms" => "true"], ): Page { // use a fresh page global $page; @@ -110,7 +112,7 @@ protected static function request( $_SERVER['REQUEST_URI'] = make_link($page_name, http_build_query($get_args)); $_GET = $get_args; $_POST = $post_args; - $_COOKIE['shm_accepted_terms'] = "true"; + $_COOKIE = $cookies; $page = new Page(); send_event(new PageRequestEvent($method, $page_name, $get_args, $post_args)); if ($page->mode == PageMode::REDIRECT) { From 978d0d629b9848a9418bc254ad1164e382c25924 Mon Sep 17 00:00:00 2001 From: Shish Date: Fri, 7 Jun 2024 14:48:34 +0100 Subject: [PATCH 017/101] [terms] add tests --- ext/terms/test.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 ext/terms/test.php diff --git a/ext/terms/test.php b/ext/terms/test.php new file mode 100644 index 000000000..3b23743ed --- /dev/null +++ b/ext/terms/test.php @@ -0,0 +1,27 @@ +request('GET', 'post/list', cookies: []); + $this->assert_text("terms-modal-enter"); + } + + public function testLoggedIn(): void + { + $this->log_in_as_user(); + $this->request('GET', 'post/list', cookies: []); + $this->assert_no_text("terms-modal-enter"); + } + + public function testCookie(): void + { + $this->request('GET', 'post/list', cookies: ['shm_accepted_terms' => 'true']); + $this->assert_no_text("terms-modal-enter"); + } +} From 51a4e753e4e207e5b0a09fa3d6c7217513ab71ae Mon Sep 17 00:00:00 2001 From: Shish Date: Fri, 7 Jun 2024 15:10:37 +0100 Subject: [PATCH 018/101] [terms] allow users to view wiki pages before accepting the terms that are written in the wiki --- ext/terms/main.php | 11 +++++++++-- ext/terms/test.php | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ext/terms/main.php b/ext/terms/main.php index 14c30bfce..7ce0959ad 100644 --- a/ext/terms/main.php +++ b/ext/terms/main.php @@ -29,8 +29,15 @@ public function onPageRequest(PageRequestEvent $event): void $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link(explode('/', $event->path, 2)[1])); } else { - // run on all pages unless logged in or cookie exists - if ($user->is_anonymous() && !isset($_COOKIE[$config->get_string('cookie_prefix', 'shm') . '_' . 'accepted_terms'])) { + // run on all pages unless any of: + // - user is logged in + // - cookie exists + // - user is viewing the wiki (because that's where the privacy policy / TOS / etc are) + if ( + $user->is_anonymous() + && !$page->get_cookie('accepted_terms') + && !$event->page_starts_with("wiki") + ) { $sitename = $config->get_string(SetupConfig::TITLE); $body = format_text($config->get_string("terms_message")); $this->theme->display_page($page, $sitename, $event->path, $body); diff --git a/ext/terms/test.php b/ext/terms/test.php index 3b23743ed..fd0f01b3d 100644 --- a/ext/terms/test.php +++ b/ext/terms/test.php @@ -24,4 +24,21 @@ public function testCookie(): void $this->request('GET', 'post/list', cookies: ['shm_accepted_terms' => 'true']); $this->assert_no_text("terms-modal-enter"); } + + public function testWiki(): void + { + $this->request('GET', 'wiki/rules'); + $this->assert_no_text("terms-modal-enter"); + } + + public function testAcceptTerms(): void + { + $page = $this->request('POST', 'accept_terms/post/list'); + $this->assertEquals($page->mode, PageMode::REDIRECT); + $this->assertEquals($page->redirect, make_link('post/list')); + + $page = $this->request('POST', 'accept_terms/'); + $this->assertEquals($page->mode, PageMode::REDIRECT); + $this->assertEquals($page->redirect, make_link('')); + } } From fc4ef117076f50828a8df5651c7711c65710bd10 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:49:43 +0000 Subject: [PATCH 019/101] [themes] convert to grid layout for mobile --- themes/danbooru/style.css | 65 ++++++++++++++++++++++++++++-------- themes/danbooru2/style.css | 58 +++++++++++++++++++++++++++----- themes/default/style.css | 54 +++++++++++++++++++++++++++--- themes/futaba/page.class.php | 4 +-- themes/futaba/style.css | 65 +++++++++++++++++++++++++++++++----- themes/lite/page.class.php | 4 ++- themes/lite/style.css | 51 ++++++++++++++++++++++++++-- themes/warm/page.class.php | 16 ++++----- themes/warm/style.css | 58 ++++++++++++++++++++++++++++++-- 9 files changed, 320 insertions(+), 55 deletions(-) diff --git a/themes/danbooru/style.css b/themes/danbooru/style.css index 32946a14d..3bd9cd75e 100644 --- a/themes/danbooru/style.css +++ b/themes/danbooru/style.css @@ -1,8 +1,20 @@ -.noleft{ -padding-left:20px; +.withleft { +margin-left: 10px; +} +ARTICLE { +grid-column: 2; +grid-row: 2; +} +ARTICLE SECTION H3 { +margin-top: 0; } HEADER { -margin-bottom:1em; +grid-column: 1 / 3; +grid-row: 1; +text-align:left; +} +HEADER h1 { +text-align:left; } HEADER #site-title { padding:10px 20px 0; @@ -34,6 +46,9 @@ HEADER #site-title { padding:10px 20px 0; } body { +display: grid; +grid-template-columns: 150px auto; +grid-gap: 0 20px; -x-system-font:none; background-color:#FFFFFF; font-family:verdana,sans-serif; @@ -94,6 +109,8 @@ padding:0 1.5em; padding-bottom:0.2em; } FOOTER { +grid-column: 1 / 3; +grid-row: 3; clear:both; color:#CCCCCC; font-size:0.9em; @@ -110,7 +127,8 @@ a:hover { text-decoration:underline; } NAV { -float:left; +grid-column: 1; +grid-row: 2; text-align:left; width:150px; padding:5px 20px 2px 10px; @@ -168,9 +186,6 @@ color: gray; .comment TD { text-align: left; } -.withleft { -margin-left:180px; -} div#paginator { clear:both; display:block; @@ -216,12 +231,6 @@ width:350px; font-size:1.5em; font-weight:bold; } -HEADER { -text-align:left; -} -HEADER h1 { -text-align:left; -} * { font-family:verdana,sans-serif; margin:0; @@ -260,6 +269,7 @@ text-align:left; } ul.flat-list li a { font-weight:normal; +display: inline-block; } #tips { margin-left:16px; @@ -275,3 +285,32 @@ margin-left:16px; margin-right:16px; font-size: 90%; } +@media screen and (width <= 800px) { +BODY { +grid-template-columns: auto; +} +HEADER { +grid-column: 1; +grid-row: 1; +} +ARTICLE { +grid-column: 1; +grid-row: 2; +} +NAV { +grid-column: 1; +grid-row: 3; +margin: auto; +width: auto; +} +FOOTER { +grid-column: 1; +grid-row: 4; +} +.withleft { +margin-left: 0; +} +.shm-image-list { +justify-content: center; +} +} diff --git a/themes/danbooru2/style.css b/themes/danbooru2/style.css index 2dd608e3f..a9bfeec5c 100644 --- a/themes/danbooru2/style.css +++ b/themes/danbooru2/style.css @@ -56,7 +56,13 @@ padding-left:2rem; } HEADER { +grid-column: 1 / 3; +grid-row: 1; margin-bottom:0.9rem; +text-align:left; +} +HEADER h1 { +text-align:left; } HEADER #site-title { margin-left: 30px; @@ -89,7 +95,6 @@ background-color: var(--header-selected); font-weight:bold; } HEADER ul#subnavbar { -margin:0 0 0.5rem; padding:0 30px 0 30px; background-color: var(--header-selected); } @@ -102,6 +107,9 @@ HEADER ul#subnavbar li:first-child { margin-left: -0.6rem; } body { +display: grid; +grid-template-columns: 11.5rem auto; +grid-gap: 0 2rem; background-color: var(--page); color: var(--text); } @@ -155,6 +163,8 @@ font-size:1.2em; padding-bottom:0.2em; } FOOTER { +grid-column: 1 / 3; +grid-row: 3; clear:both; border-top:solid 1px #E7E7F7; margin-top:1rem; @@ -175,7 +185,8 @@ a:hover { text-decoration:underline; } NAV { -float:left; +grid-column: 1; +grid-row: 2; padding:0 1rem 0.2rem 2rem; width:11.5rem; text-align:left; @@ -240,7 +251,7 @@ color: var(--comment-meta); text-align: left; } .withleft { -margin-left:14.5rem; +margin-left: 1rem; } div#paginator { display:block; @@ -313,12 +324,6 @@ padding:0.2rem 0.6rem; font-weight:bold; font-size:1.5em; } -HEADER { -text-align:left; -} -HEADER h1 { -text-align:left; -} * { margin:0; padding:0; @@ -381,6 +386,8 @@ text-align:center; border-radius:0.5rem; } ARTICLE { +grid-column: 2; +grid-row: 2; margin-right:1rem; } ARTICLE section + section { @@ -392,3 +399,36 @@ margin-top:0.5rem; #Imagemain h3 { display:none; } +@media screen and (width <= 800px) { +BODY { +grid-template-columns: auto; +} +HEADER { +grid-column: 1; +grid-row: 1; +} +ARTICLE { +grid-column: 1; +grid-row: 2; +margin: 0 16px; +} +NAV { +grid-column: 1; +grid-row: 3; +margin: auto; +width: auto; +} +FOOTER { +grid-column: 1; +grid-row: 4; +} +.withleft { +margin: 0; +} +#image-list .blockbody { +margin: 0; +} +.shm-image-list { +justify-content: center; +} +} diff --git a/themes/default/style.css b/themes/default/style.css index 0746f9ac0..556d2f681 100644 --- a/themes/default/style.css +++ b/themes/default/style.css @@ -52,14 +52,21 @@ font-family: sans-serif; } +HEADER { + grid-column: 1 / 3; + grid-row: 1; +} HEADER H1 { max-height: 3em; overflow: hidden; } BODY { + display: grid; + grid-template-columns: 216px auto; + grid-gap: 0 10px; background: var(--page); color: var(--text); - margin: 0; + margin: 0; } H1 { background: var(--title); @@ -105,11 +112,14 @@ TABLE.zebra TR:nth-child(odd) {background: var(--zebra-odd);} TABLE.zebra TR:nth-child(even) {background: var(--zebra-even);} FOOTER { + grid-column: 1 / 3; + grid-row: 3; clear: both; font-size: 0.7rem; text-align: center; background: var(--title); border: 1px solid var(--title-border); + margin-top: 0; } A { @@ -132,8 +142,8 @@ UL { * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ NAV { - width: 200px; - float: left; + grid-column: 1; + grid-row: 2; text-align: center; margin-left: 16px; } @@ -188,9 +198,10 @@ TABLE.tag_list>TBODY>TR>TD:after { * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ARTICLE { - margin-left: 226px; + grid-column: 2; + grid-row: 2; margin-right: 16px; - margin-top: 16px; + margin-top: 0; text-align: center; height: 1%; } @@ -199,6 +210,39 @@ ARTICLE TABLE { margin: auto; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* mobile screens * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +@media screen and (width <= 800px) { + BODY { + grid-template-columns: auto; + } + HEADER { + grid-column: 1; + grid-row: 1; + } + ARTICLE { + grid-column: 1; + grid-row: 2; + margin-right: 0; + } + NAV { + grid-column: 1; + grid-row: 3; + margin: auto; + } + FOOTER { + grid-column: 1; + grid-row: 4; + } + #image-list .blockbody { + margin: 0; + } + .shm-image-list { + justify-content: center; + } +} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * specific page types * diff --git a/themes/futaba/page.class.php b/themes/futaba/page.class.php index bfb570407..69513440c 100644 --- a/themes/futaba/page.class.php +++ b/themes/futaba/page.class.php @@ -37,10 +37,8 @@ public function body_html(): string if ($this->left_enabled) { $left = ""; - $withleft = "withleft"; } else { $left = ""; - $withleft = ""; } $flash_html = $this->flash ? "".nl2br(html_escape(implode("\n", $this->flash)))."" : ""; @@ -53,7 +51,7 @@ public function body_html(): string $sub_block_html $left -
+
$flash_html $main_block_html
diff --git a/themes/futaba/style.css b/themes/futaba/style.css index 19f127e23..5b3d00183 100644 --- a/themes/futaba/style.css +++ b/themes/futaba/style.css @@ -8,13 +8,16 @@ } BODY { + display: grid; + grid-template-columns: 200px auto; + grid-gap: 0 16px; + margin: 0; background: #FFFFEE url(fade.png) top center repeat-x; color: #800000; padding-left: 5px; padding-right: 5px; - margin-right: 0; - margin-left: 0; - margin-top: 5px; + margin: 0; + margin-bottom: 8px; } H1 { text-align: center; @@ -23,7 +26,13 @@ H1 { display: none; } +HEADER { + grid-column: 1 / 3; + grid-row: 1; +} FOOTER { + grid-column: 1 / 3; + grid-row: 3; clear: both; padding-top: 8px; font-size: 0.7rem; @@ -39,8 +48,9 @@ HR {border: none; border-top: 1px solid #D9BFB7; height: 0; clear: both;} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ NAV { + grid-column: 1; + grid-row: 2; width: 200px; - float: left; text-align: center; margin-left: 16px; } @@ -64,9 +74,6 @@ NAV SELECT { NAV H3 { text-align: center; } -.withleft { - margin-left: 160px; -} #paginator .blockbody { background: none; @@ -79,9 +86,11 @@ NAV H3 { * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ARTICLE { - margin-left: 226px; + grid-column: 2; + grid-row: 2; + margin-left: 0; margin-right: 16px; - margin-top: 16px; + margin-top: 0; text-align: center; height: 1%; } @@ -89,6 +98,9 @@ ARTICLE TABLE { width: 90%; margin: auto; } +ARTICLE SECTION H3 { + margin-top: 0; +} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * the navigation bar, and all its blocks * @@ -109,6 +121,41 @@ TABLE.tag_list>TBODY>TR>TD:after { content: " "; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* mobile screens * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +@media screen and (width <= 800px) { + BODY { + grid-template-columns: auto; + } + HEADER { + grid-column: 1; + grid-row: 1; + } + ARTICLE { + grid-column: 1; + grid-row: 2; + margin-right: 0; + } + NAV { + grid-column: 1; + grid-row: 3; + margin: auto; + width: auto; + } + FOOTER { + grid-column: 1; + grid-row: 4; + } + #image-list .blockbody { + margin: 0; + } + .shm-image-list { + justify-content: center; + } +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * specific page types * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff --git a/themes/lite/page.class.php b/themes/lite/page.class.php index 9f2ef8bf4..eb1b89612 100644 --- a/themes/lite/page.class.php +++ b/themes/lite/page.class.php @@ -32,10 +32,12 @@ public function body_html(): string {$site_name} "; // Custom links: These appear on the menu. - $custom_links = ""; + $custom_links = "
"; foreach ($nav_links as $nav_link) { $custom_links .= $this->navlinks($nav_link->link, $nav_link->description, $nav_link->active); } + $custom_links .= "
"; + $menu .= "{$custom_links}"; $left_block_html = ""; diff --git a/themes/lite/style.css b/themes/lite/style.css index 03cb7f5ba..293a33d6a 100644 --- a/themes/lite/style.css +++ b/themes/lite/style.css @@ -8,6 +8,9 @@ font-size: 14px; } BODY { + display: grid; + grid-template-columns: 210px auto; + grid-gap: 0 16px; background: #F0F7FF; margin: 0; } @@ -30,6 +33,9 @@ a.tab:hover, a.tab:active, .tab-selected { background-color:#FFFFFE; text-decoration:none; } +.bar .tab, .bar .tab-selected { + display: inline-block; +} .tab, .tab-selected, .tframe, #tips { -moz-border-radius:4px; -webkit-border-radius:4px; @@ -147,6 +153,8 @@ INPUT:hover, button:hover, TEXTAREA:hover { } FOOTER { + grid-column: 1 / 3; + grid-row: 3; clear: both; padding: 8px; font-size: 0.7rem; @@ -155,6 +163,11 @@ FOOTER { background: #E3EFFA; } +HEADER { + grid-column: 1 / 3; + grid-row: 1; +} + A {text-decoration: none;} A:hover {text-decoration: underline;} @@ -173,8 +186,9 @@ UL { * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ NAV { + grid-column: 1; + grid-row: 2; width: 200px; - float: left; text-align: center; margin-left: 16px; } @@ -257,7 +271,8 @@ TABLE.tag_list>TBODY>TR>TD:after { * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ARTICLE { - margin-left: 226px; + grid-column: 2; + grid-row: 2; margin-right: 16px; text-align: center; height: 1%; @@ -275,6 +290,38 @@ ARTICLE TABLE { width: 90%; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* mobile screens * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +@media screen and (width <= 800px) { + BODY { + grid-template-columns: auto; + } + HEADER { + grid-column: 1; + grid-row: 1; + } + ARTICLE { + grid-column: 1; + grid-row: 2; + margin: 0 16px; + } + NAV { + grid-column: 1; + grid-row: 3; + margin: auto; + width: auto; + } + FOOTER { + grid-column: 1; + grid-row: 4; + } + .shm-image-list { + justify-content: center; + } +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * specific page types * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff --git a/themes/warm/page.class.php b/themes/warm/page.class.php index 7e38aa5e7..fd6992073 100644 --- a/themes/warm/page.class.php +++ b/themes/warm/page.class.php @@ -25,7 +25,7 @@ public function body_html(): string $left_block_html .= $block->get_html(true); break; case "head": - $head_block_html .= "".$block->get_html(false).""; + $head_block_html .= "".$block->get_html(false).""; break; case "main": $main_block_html .= $block->get_html(false); @@ -44,15 +44,11 @@ public function body_html(): string return << - - - - $head_block_html - - +
+

{$site_name}

+ +
+ $head_block_html $sub_block_html