diff --git a/assets/less/mio/classes/avatar.less b/assets/less/mio/classes/avatar.less index 80e5fb1a..f7025824 100644 --- a/assets/less/mio/classes/avatar.less +++ b/assets/less/mio/classes/avatar.less @@ -1,4 +1,4 @@ -.mio__avatar { +.avatar { flex-shrink: 0; background-color: #fbeeff; background-size: cover; diff --git a/assets/less/mio/classes/container.less b/assets/less/mio/classes/container.less index 92f52ba6..87d90f12 100644 --- a/assets/less/mio/classes/container.less +++ b/assets/less/mio/classes/container.less @@ -1,16 +1,31 @@ -.mio__container { +.container { border: 1px solid #9475b2; background-color: #fbeeff; margin: 2px 0; &__title { + display: block; + text-decoration: none; background-color: #9475b2; color: #306; font-size: 1.17em; font-weight: 700; padding: 3px; font-family: @mio-font-heading; + + &--link:hover { + text-decoration: underline; + } + + &__link { + color: inherit; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } } &__content { diff --git a/assets/less/mio/classes/footer.less b/assets/less/mio/classes/footer.less index c90c5a7e..7a6593b5 100644 --- a/assets/less/mio/classes/footer.less +++ b/assets/less/mio/classes/footer.less @@ -1,4 +1,4 @@ -.mio__footer { +.footer { text-align: center; font-size: .9em; line-height: 1.5em; diff --git a/assets/less/mio/classes/forum/listing.less b/assets/less/mio/classes/forum/listing.less index 62d67f71..7c0a96c1 100644 --- a/assets/less/mio/classes/forum/listing.less +++ b/assets/less/mio/classes/forum/listing.less @@ -1,6 +1,6 @@ @mio-forum-listing-mobile: 500px; -.mio__forum__listing { +.forum__listing { &__forums { margin: 0; } diff --git a/assets/less/mio/classes/header.less b/assets/less/mio/classes/header.less index 959ef552..a3d88213 100644 --- a/assets/less/mio/classes/header.less +++ b/assets/less/mio/classes/header.less @@ -1,6 +1,6 @@ @mio-header-mobile: 700px; -.mio__header { +.header { display: flex; margin: 4px 0; @@ -26,6 +26,7 @@ @media (max-width: @mio-header-mobile) { max-width: 200px; max-height: 100px; + margin-bottom: 4px; } } } diff --git a/assets/less/mio/classes/heading.less b/assets/less/mio/classes/heading.less index a261de69..1f373d16 100644 --- a/assets/less/mio/classes/heading.less +++ b/assets/less/mio/classes/heading.less @@ -1,4 +1,4 @@ -.mio__heading { +.heading { &--1 { line-height: 1.2em; } diff --git a/assets/less/mio/classes/input/button.less b/assets/less/mio/classes/input/button.less index 3064a75a..e17370aa 100644 --- a/assets/less/mio/classes/input/button.less +++ b/assets/less/mio/classes/input/button.less @@ -1,4 +1,4 @@ -.mio__input__button { +.input__button { font-family: 'visitor1'; font-size: 20px; line-height: 1.25em; diff --git a/assets/less/mio/classes/input/text.less b/assets/less/mio/classes/input/text.less index d933bc21..df90e5ac 100644 --- a/assets/less/mio/classes/input/text.less +++ b/assets/less/mio/classes/input/text.less @@ -1,4 +1,4 @@ -.mio__input__text { +.input__text { border: 1px solid #aaa; padding: 1px; background: #fff; @@ -9,7 +9,7 @@ } } -.mio--dark .mio__input__text { +.mio--dark .input__text { background: #111; color: #fff; } diff --git a/assets/less/mio/classes/input/textarea.less b/assets/less/mio/classes/input/textarea.less index 24c2827a..43707219 100644 --- a/assets/less/mio/classes/input/textarea.less +++ b/assets/less/mio/classes/input/textarea.less @@ -1,4 +1,4 @@ -.mio__input__textarea { +.input__textarea { border: 1px solid #aaa; padding: 1px; vertical-align: bottom; @@ -10,7 +10,7 @@ } } -.mio--dark .mio__input__textarea { +.mio--dark .input__textarea { background: #111; color: #fff; } diff --git a/assets/less/mio/classes/input/upload.less b/assets/less/mio/classes/input/upload.less index a8d8bb71..83a2aa5d 100644 --- a/assets/less/mio/classes/input/upload.less +++ b/assets/less/mio/classes/input/upload.less @@ -1,7 +1,7 @@ -.mio__input__upload { +.input__upload { display: none; &__label { - .mio__input__button(); + .input__button(); } } diff --git a/assets/less/mio/classes/navigation.less b/assets/less/mio/classes/navigation.less index db5af422..0fb10cb4 100644 --- a/assets/less/mio/classes/navigation.less +++ b/assets/less/mio/classes/navigation.less @@ -1,6 +1,6 @@ @mio-navigation-mobile: 1000px; -.mio__navigation { +.navigation { margin: 5px 0; width: 100%; display: flex; @@ -22,7 +22,7 @@ border-bottom-width: 1px; align-items: flex-end; - .mio__navigation__option { + .navigation__option { border-top-width: 1px; border-bottom-width: 0; @@ -68,7 +68,7 @@ } @media (min-width: @mio-navigation-mobile) { - .mio__navigation__link { + .navigation__link { padding: 3px 1em; } } @@ -94,20 +94,20 @@ } .mio--dark { - .mio__navigation, - .mio__navigation__option { + .navigation, + .navigation__option { border-color: #9475b2; } - .mio__navigation__option { + .navigation__option { background-color: #462e55; } - .mio__navigation__option--selected { + .navigation__option--selected { background-color: #23172a; } - .mio__navigation__link { + .navigation__link { color: #9475b2; &:hover { diff --git a/assets/less/mio/classes/news/container.less b/assets/less/mio/classes/news/container.less new file mode 100644 index 00000000..5ba39c69 --- /dev/null +++ b/assets/less/mio/classes/news/container.less @@ -0,0 +1,18 @@ +@mio-news-mobile: 700px; + +.news__container { + margin: 0; + + &:not(:last-child) { + margin-bottom: 2px; + } + + &__content { + margin: 2px; + display: flex; + + @media (max-width: @mio-news-mobile) { + flex-direction: column; + } + } +} diff --git a/assets/less/mio/classes/news/list.less b/assets/less/mio/classes/news/list.less new file mode 100644 index 00000000..75545549 --- /dev/null +++ b/assets/less/mio/classes/news/list.less @@ -0,0 +1,28 @@ +.news__list { + margin: 0; + margin-bottom: 2px; + + &__item { + text-decoration: none; + color: inherit; + display: block; + + &:hover { + text-decoration: underline; + } + + &--kvp { + display: flex; + } + } + + &__name { + flex-shrink: 1; + flex-grow: 1; + } + + &__value { + flex-shrink: 0; + flex-grow: 0; + } +} diff --git a/assets/less/mio/classes/news/pagination.less b/assets/less/mio/classes/news/pagination.less new file mode 100644 index 00000000..131931a4 --- /dev/null +++ b/assets/less/mio/classes/news/pagination.less @@ -0,0 +1,40 @@ +.news__pagination { + border: 1px solid #9475b2; + list-style: none; + display: flex; + justify-content: space-between; + padding: 1px; + + &__option { + background: #9475b2; + height: 20px; + width: 20px; + + @media (max-width: @mio-news-mobile) { + height: 30px; + width: 30px; + font-size: 1.5em; + line-height: 1.5em; + } + } + + &__link { + display: block; + width: 100%; + height: 100%; + text-align: center; + text-decoration: none; + color: #306; + + &--prev, + &--next, + &--active, + &:hover { + font-weight: bold; + } + } + + &__separator { + display: none; + } +} diff --git a/assets/less/mio/classes/news/post.less b/assets/less/mio/classes/news/post.less new file mode 100644 index 00000000..ad6eddd8 --- /dev/null +++ b/assets/less/mio/classes/news/post.less @@ -0,0 +1,67 @@ +.news__post { + &__content { + margin: 2px; + display: flex; + + @media (max-width: @mio-news-mobile) { + flex-direction: column; + } + } + + &__text { + margin-left: 2px; + flex-grow: 1; + flex-shrink: 1; + } + + &__details { + width: 200px; + + @media (max-width: @mio-news-mobile) { + width: 100%; + } + } + + &__detail { + border: 1px solid #9475b2; + padding: 1px; + + &:not(:last-child) { + margin-bottom: 2px; + } + } + + &__user { + display: flex; + align-items: center; + text-decoration: none; + color: inherit; + } + + &__avatar { + text-align: right; + width: 50px; + height: 50px; + } + + &__username { + flex-grow: 1; + flex-shrink: 1; + font-weight: 700; + font-size: 1.5em; + line-height: 1.2em; + text-align: center; + } + + &__info { + display: flex; + justify-content: space-between; + padding: 1px 4px; + text-decoration: none; + color: inherit; + + &:hover { + text-decoration: underline; + } + } +} diff --git a/assets/less/mio/classes/news/preview.less b/assets/less/mio/classes/news/preview.less new file mode 100644 index 00000000..18ea6914 --- /dev/null +++ b/assets/less/mio/classes/news/preview.less @@ -0,0 +1,45 @@ +.news__preview { + margin: 0; + + &:not(:last-child) { + margin-bottom: 2px; + } + + &__listing { + flex-grow: 1; + flex-shrink: 1; + } + + &__content { + display: flex; + margin: 2px; + } + + &__text { + flex-grow: 1; + flex-shrink: 1; + margin-left: 2px; + } + + &__info { + text-align: right; + flex-grow: 0; + flex-shrink: 0; + } + + &__user { + text-decoration: none; + color: inherit; + display: inline-flex; + + &__name { + font-weight: 700; + } + + &__avatar { + height: 20px; + width: 20px; + margin-left: 4px; + } + } +} diff --git a/assets/less/mio/classes/news/sidebar.less b/assets/less/mio/classes/news/sidebar.less new file mode 100644 index 00000000..15796202 --- /dev/null +++ b/assets/less/mio/classes/news/sidebar.less @@ -0,0 +1,12 @@ +.news__sidebar { + width: 300px; + flex-grow: 0; + flex-shrink: 0; + margin-left: 2px; + + @media (max-width: @mio-news-mobile) { + margin: 0; + width: 100%; + margin-top: 2px; + } +} diff --git a/assets/less/mio/classes/profile.less b/assets/less/mio/classes/profile.less index 227de7fc..ab758a74 100644 --- a/assets/less/mio/classes/profile.less +++ b/assets/less/mio/classes/profile.less @@ -1,6 +1,6 @@ @mio-profile-mobile: 700px; -.mio__profile { +.profile { &__avatar { width: 200px; height: 200px; diff --git a/assets/less/mio/classes/settings/account.less b/assets/less/mio/classes/settings/account.less index e8357307..e20d71e3 100644 --- a/assets/less/mio/classes/settings/account.less +++ b/assets/less/mio/classes/settings/account.less @@ -1,9 +1,14 @@ @mio-settings-account-mobile: 800px; -.mio__settings__account { +.settings__account { display: flex; flex-direction: column; + &__disabled { + text-align: center; + padding: 5px; + } + &__row { width: 100%; display: flex; @@ -24,11 +29,17 @@ &__column { flex-grow: 1; - &:not(.mio__settings__account__column--no-margin) { + &:not(.settings__account__column--no-margin) { margin: 1px; border: 1px solid #9475b2; border-top-width: 0; } + + @media (min-width: @mio-settings-account-mobile) { + &--disabled { + max-width: 400px; + } + } } &__title { diff --git a/assets/less/mio/classes/settings/avatar.less b/assets/less/mio/classes/settings/avatar.less index efa32a49..4027df0e 100644 --- a/assets/less/mio/classes/settings/avatar.less +++ b/assets/less/mio/classes/settings/avatar.less @@ -1,6 +1,6 @@ @mio-settings-avatar-mobile: 700px; -.mio__settings__avatar { +.settings__avatar { display: flex; min-height: 200px; justify-content: space-between; diff --git a/assets/less/mio/classes/settings/content.less b/assets/less/mio/classes/settings/content.less index 15ec69f6..657d189c 100644 --- a/assets/less/mio/classes/settings/content.less +++ b/assets/less/mio/classes/settings/content.less @@ -1,4 +1,4 @@ -.mio__settings__content { +.settings__content { &--account, &--sessions, &--login-history { diff --git a/assets/less/mio/classes/settings/description.less b/assets/less/mio/classes/settings/description.less index 4a10897a..ff73619a 100644 --- a/assets/less/mio/classes/settings/description.less +++ b/assets/less/mio/classes/settings/description.less @@ -1,4 +1,4 @@ -.mio__settings__description { +.settings__description { font-size: .9em; padding: 1px 4px; border-bottom: 1px solid #9475b2; diff --git a/assets/less/mio/classes/settings/errors.less b/assets/less/mio/classes/settings/errors.less index fc15bfc8..138f384f 100644 --- a/assets/less/mio/classes/settings/errors.less +++ b/assets/less/mio/classes/settings/errors.less @@ -1,4 +1,4 @@ -.mio__settings__errors { +.settings__errors { margin-left: 1.2em; list-style: square; } diff --git a/assets/less/mio/classes/settings/login-history.less b/assets/less/mio/classes/settings/login-history.less index 729e253a..b057c6e0 100644 --- a/assets/less/mio/classes/settings/login-history.less +++ b/assets/less/mio/classes/settings/login-history.less @@ -1,4 +1,4 @@ -.mio__settings__login-history { +.settings__login-history { &__country { vertical-align: middle; } diff --git a/assets/less/mio/classes/settings/sessions.less b/assets/less/mio/classes/settings/sessions.less index 74ca134b..42c0434c 100644 --- a/assets/less/mio/classes/settings/sessions.less +++ b/assets/less/mio/classes/settings/sessions.less @@ -1,6 +1,6 @@ @mio-settings-sessions-mobile: 1000px; -.mio__settings__sessions { +.settings__sessions { &__country { vertical-align: middle; } diff --git a/assets/less/mio/main.less b/assets/less/mio/main.less index 051b243f..c3e8fb4e 100644 --- a/assets/less/mio/main.less +++ b/assets/less/mio/main.less @@ -61,5 +61,13 @@ body { @import "classes/settings/login-history"; @import "classes/settings/sessions"; +// News +@import "classes/news/container"; +@import "classes/news/list"; +@import "classes/news/pagination"; +@import "classes/news/preview"; +@import "classes/news/sidebar"; +@import "classes/news/post"; // post needs to be able to override sidebar + // Forums @import "classes/forum/listing"; diff --git a/build.sh b/build.sh index 8cb8d2c5..939de00d 100644 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash ASSETS_PATH='./assets' ASSETS_LESS="$ASSETS_PATH/less" diff --git a/public/index.php b/public/index.php index 0ebee2c0..684fc107 100644 --- a/public/index.php +++ b/public/index.php @@ -1,4 +1,8 @@ templating->render('home.landing'); +$featured_news = NewsPost::where('is_featured', true)->orderBy('created_at', 'desc')->take(3)->get(); + +echo $app->templating->render('home.landing', compact('featured_news')); diff --git a/public/news.php b/public/news.php index 443a2f7c..4acf0df4 100644 --- a/public/news.php +++ b/public/news.php @@ -4,8 +4,9 @@ use Misuzu\News\NewsPost; require_once __DIR__ . '/../misuzu.php'; -$category_id = empty($_GET['c']) ? null : (int)$_GET['c']; -$post_id = empty($_GET['n']) ? null : (int)$_GET['n']; +$category_id = isset($_GET['c']) ? (int)$_GET['c'] : null; +$post_id = isset($_GET['n']) ? (int)$_GET['n'] : null; +$page_id = (int)($_GET['p'] ?? 1); if ($post_id !== null) { $post = NewsPost::find($post_id); @@ -29,13 +30,26 @@ if ($category_id !== null) { return; } - $posts = $category->posts()->orderBy('created_at', 'desc')->paginate(5); - $featured = $category->where('is_featured', 1)->orderBy('created_at', 'desc')->take(10); - echo $app->templating->render('news.category', compact('category', 'posts', 'featured')); + $posts = $category->posts()->orderBy('created_at', 'desc')->paginate(5, ['*'], 'p', $page_id); + + if (!is_valid_page($posts, $page_id)) { + http_response_code(404); + echo $app->templating->render('errors.404'); + return; + } + + $featured = $category->posts()->where('is_featured', 1)->orderBy('created_at', 'desc')->take(10)->get(); + echo $app->templating->render('news.category', compact('category', 'posts', 'featured', 'page_id')); return; } $categories = NewsCategory::where('is_hidden', false)->get(); -$posts = NewsPost::where('is_featured', true)->paginate(5); +$posts = NewsPost::where('is_featured', true)->orderBy('created_at', 'desc')->paginate(5, ['*'], 'p', $page_id); -echo $app->templating->render('news.index', compact('categories', 'posts')); +if (!is_valid_page($posts, $page_id)) { + http_response_code(404); + echo $app->templating->render('errors.404'); + return; +} + +echo $app->templating->render('news.index', compact('categories', 'posts', 'page_id')); diff --git a/src/News/NewsPost.php b/src/News/NewsPost.php index f4a8612c..cec78208 100644 --- a/src/News/NewsPost.php +++ b/src/News/NewsPost.php @@ -4,6 +4,7 @@ namespace Misuzu\News; use Illuminate\Database\Eloquent\SoftDeletes; use Misuzu\Users\User; use Misuzu\Model; +use Parsedown; final class NewsPost extends Model { @@ -12,6 +13,11 @@ final class NewsPost extends Model protected $table = 'news_posts'; protected $primaryKey = 'post_id'; + public function getHtml(): string + { + return (new Parsedown)->text($this->post_text); + } + public function user() { return $this->belongsTo(User::class, 'user_id'); diff --git a/utility.php b/utility.php index b7a8a95f..30a774c6 100644 --- a/utility.php +++ b/utility.php @@ -212,3 +212,8 @@ function first_paragraph(string $text, string $delimiter = "\n"): string $index = mb_strpos($text, $delimiter); return $index === false ? $text : mb_substr($text, 0, $index); } + +function is_valid_page(\Illuminate\Pagination\LengthAwarePaginator $paginator, int $attemptedPage): bool +{ + return $attemptedPage >= 1 && $attemptedPage <= $paginator->lastPage(); +} diff --git a/views/manage/macros.twig b/views/manage/macros.twig index cd11efb3..0f2f567e 100644 --- a/views/manage/macros.twig +++ b/views/manage/macros.twig @@ -17,7 +17,7 @@ {% macro paginate(paginator, base_url, className, alwaysRender) %} {% set alwaysRender = alwaysRender|default(false) %} - {% if alwaysRender or paginator.hasMorePages %} + {% if alwaysRender or paginator.lastPage > 1 %} {% set separator = '%3F' in base_url|default('')|url_encode ? '&' : '?' %} {% set base_url = base_url ~ separator %} diff --git a/views/mio/errors/master.twig b/views/mio/errors/master.twig index 09c899a5..dd43d3a9 100644 --- a/views/mio/errors/master.twig +++ b/views/mio/errors/master.twig @@ -2,9 +2,9 @@ {% from '@mio/macros.twig' import navigation %} {% block content %} -
Try again later, perhaps.
{% endblock %} diff --git a/views/mio/home/landing.twig b/views/mio/home/landing.twig index 9109ed1d..57b7fc89 100644 --- a/views/mio/home/landing.twig +++ b/views/mio/home/landing.twig @@ -1,24 +1,27 @@ {% extends '@mio/home/master.twig' %} {% from '@mio/macros.twig' import navigation, link %} +{% from '@mio/news/macros.twig' import news_preview %} {% set canonical_url = '/' %} {% block content %} -Welcome to Flashii, the site is still heavily in development. You can follow us on {{ link('https://twitter.com/flashiinet', 'Twitter') }} where we'll post updates every so often, we'll also announce when the site is ready for public use there!
- {% if app.session == null %} -You can create an account already though, if you'd like!
- {% else %} -If you want a custom avatar, let me (flash) know and I'll set it for you. The settings page doesn't exist yet..
- {% endif %} + {% if app.session != null %} +You have 0 new messages because the PM system doesn't exist yet, have a nice day.
+I decided to shelve it for a bit. I'm working on this all by myself and I'm not a designer, so coming up with good designs that flow nicely together isn't easy for me.
-This layout is a LOT simpler to work with than the other one, so this'll be the main design until later.
-A dark mode will also be available at a later date and for those that grow attached this to javascript light style, you will eventually be able to switch to this design whenever you like from your settings!
+ {% endif %} + +