* Factor out the post navbar into a component. The post navbar is the
part of the post containing the current search, the list of pools, and
the list of favgroups, along with next/prev navigation links.
* Change navbar markup: remove various unused CSS classes/IDs, change
pools to use same markup as favgroups, replace nested <div>'s with
flat <ul>/<li> list.
* Use CSS to truncate long searches/pool names/favgroup names if they're
too wide for the screen (especially on mobile).
Change post votes to work the same way as comment votes:
* Make the upvote arrow blue if you've upvoted the post, or grey if you
haven't. Likewise for the downvote arrow.
* Make it so you can click the upvote or downvote arrows to undo the vote.
* Don't show any notices when you vote on a post.
Also fix it so that votes work the same way on the posts page, the
comments page, and in the modqueue. Before it wasn't possible to undo
votes on the comments page or in the modqueue.
When an anonymous users tries to go to the new upload page, direct them
to the login page instead of showing them an "Access Denied" error.
Fixes complaints from SEO tools about linking to pages that return a 403
error.
Factor out FontAwesome icons into a set of helpers. This is so that it's
easier to keep track of which icons we're using and easier to change
icons globally.
Refactor the post preview html to use the ViewComponent framework. This
lets us encapsulate all the HTML, CSS, and helper methods for a UI
component in a single place.
See https://viewcomponent.org.
Add a Restricted user level. Restricted users are level 10, below
Members. New users start out as Restricted if they sign up from a proxy
or an IP recently used by another user.
Restricted users can't update or edit any public content on the site
until they verify their email address, at which point they're promoted
to Member. Restricted users are only allowed to do personal actions
like keep favorites, keep favgroups and saved searches, mark dmails as
read or deleted, or mark forum posts as read.
The restricted state already existed before, the only change here is
that now it's an actual user level instead of a hidden state. Before it
was based on two hidden flags on the user, the `requires_verification`
flag (set when a user signs up from a proxy, etc), and the `is_verified`
flag (set after the user verifies their email). Making it a user level
means that now the Restricted status will be shown publicly.
Introducing a new level below Member means that we have to change every
`is_member?` check to `!is_anonymous` for every place where we used
`is_member?` to check that the current user is logged in.
Regenerate posts asynchronously using a delayed job.
Regenerating a post can be slow because it involves downloading the
original file, regenerating the thumbnails, and redistributing the new
thumbnails back to the image servers. It's better to run this in the
background, especially if a user is trying to regenerate posts in bulk.
The downside is there's no notification to the user when the regeneration
is complete. You have to check the modactions log to see when it's finished.
* Remove the PostRegeneration model. Instead just use a mod action
to log when a post is regenerated.
* Change it so that IQDB is also updated when the image samples are
regenerated. This is necessary because when the images samples are
regenerated, the thumbnail may change, which means IQDB needs to be
updated too. This can happen when regenerating old images with
transparent backgrounds where the transparency was flattened to black
instead of white in the thumbnail.
* Only display one "Regenerate image" option in the post sidebar, to
regenerate both the images and IQDB. Regenerating IQDB only can be
done through the API. Having two options in the sidebar is too much
clutter, and it's too confusing for Mods who don't know the difference
between an IQDB-only regeneration and a full image regeneration.
* Add a confirm prompt to the "Regenerate image" link.
Disable the browser's native spellchecking ability on all form inputs,
except for DText inputs. We do this by setting `spellcheck="false"` on
the <body> tag, and `spellcheck="true"` on DText <input> tags.
This fixes browsers displaying a red wavy underline beneath tags in the
tag search box, among other places. We disable spellchecking globally
because most form inputs, except for DText inputs, aren't meant for
natural English language.
* Remove the data-is-favorited attribute from post thumbnails.
* Remove the is_favorited attribute from the /posts.json API.
* Remove the fav_string attribute from the /posts.json API (only visible
to moderators).
* Change `Post#favorited_by?` to not use the fav_string.
Further addresses #4652 by eliminating the last places where fav_string
was used.
On the posts show page, in the favorites list, show favorites according
to the order they were added to the favorites table, rather than the
order they were added to the posts's fav_string.
On most posts these should be the same, but on old posts they may be
slightly different. The IDs of the first few hundred thousand favorites
don't appear to be in chronological order. Probably the original
favorite IDs were lost and recreated by a database move at some point in
Danbooru's history. The fav_string is also inconsistent with the
favorites table in some places (one contains favorites that aren't
contained by the other), which also throws off the order.
Partially addresses #4562 by eliminating one place where we depended on
the fav_string.
* Only show the current pending flag on flagged posts. Don't show old flags.
* Don't show both the "This post was flagged for review" and the "This
post was flagged and is pending" notices.
* Only show the current pending appeal in the "This post was appealed"
notice. Don't show old appeals.
* Don't show both the "This post was deleted" and the "This post was
appealed" notice on appealed posts. Only show the "This post was
appealed" notice.
* Show "no reason" if no appeal reason was given.
* Include appealed posts in the modqueue.
* Add `status` field to appeals. Appeals start out as `pending`, then
become `rejected` if the post isn't approved within three days. If the
post is approved, the appeal's status becomes `succeeded`.
* Add `status` field to flags. Flags start out as `pending` then become
`rejected` if the post is approved within three days. If the post
isn't approved, the flag's status becomes `succeeded`.
* Leave behind a "Unapproved in three days" dummy flag when an appeal
goes unapproved, just like when a pending post is unapproved.
* Only allow deleted posts to be appealed. Don't allow flagged posts to be appealed.
* Add `status:appealed` metatag. `status:appealed` is separate from `status:pending`.
* Include appealed posts in `status:modqueue`. Search `status:modqueue order:modqueue`
to view the modqueue as a normal search.
* Retroactively set old flags and appeals as succeeded or rejected. This
may not be correct for posts that were appealed or flagged multiple
times. This is difficult to set correctly because we don't have
approval records for old posts, so we can't tell the actual outcome of
old flags and appeals.
* Deprecate the `is_resolved` field on post flags. A resolved flag is a
flag that isn't pending.
* Known bug: appealed posts have a black border instead of a blue
border. Checking whether a post has been appealed would require either
an extra query on the posts/index page, or an is_appealed flag on
posts, neither of which are very desirable.
* Known bug: you can't use `status:appealed` in blacklists, for the same
reason as above.
Rework post deletion from using a separate page to using a dialog box,
like flagging.
* Add `DELETE /posts/:id` endpoint.
* Remove `POST /moderator/post/posts/:id/delete` endpoint.
Rewrite the tag counter widget (the one above the tag edit box) to use
React. This is a trial run for using React elsewhere.
We actually use Preact instead of React because it's lighter weight.
We use Mobx for state management because it's cleaner than React's
setState or useState.
This incidentally fixes a couple bugs:
* The tag counter wasn't updated when deleting tags with backspace
* The tag counter wasn't updated when pasting in new tags.
Standardize font sizes and heading tags (<h1>-<h6>) to be more
consistent across the site.
Changes:
* Introduce font size CSS variables and start replacing hardcoded font
sizes with standard sizes.
* Change header tags to use only one <h1> per page. One <h1> per page is
recommended for SEO purposes. Usually this is for the page title, like
in forum threads or wiki pages.
* Standardize on <h2> for section headers in sidebars and <h3> for
smaller subsection headers. Don't use <h4>-<h6>.
* In DText, make h1-h4 headers all the same size. Standard wiki style is
to ignore h1-h3 and start at h4.
* In DText, make h4-h6 the same size as the h1-h3 tags outside of DText.
* In the tag list, change the <h1> and <h2> tag category headers to <h3>.
* Make usernames in comments and forum posts smaller. Also change the
<h4> tag for the commenter name to <div class="author-name">.
* Make the tag list, paginator, and nav menu smaller on mobile.
* Change h1#app-name-header to a#app-name-header.
Add rel=nofollow to various internal search links to prevent Google from
attempting to crawl things like `<tag> status:deleted` or `approver:<name>`
searches.
* Fix incorrect canonical tags. Before we were using
`<meta name="canonical" content="...">`. This is wrong, it should have been
`<link rel="canonical" href="...">`.
* Add a default canonical tag on all pages. Fixes Google treating the
same content on different subdomains (safebooru, shima, kagamihara, etc)
as duplicate content. Also fixes Google sometimes treating similar but
distinct content on the same domain as duplicate content.
Fix the sidebar on the /posts index page sometimes being blank. This
could happen when either the related tag calculation was too slow and
timed out, or when Reporbooru was unavailable and we couldn't fetch the
list of popular tags.
In the tag list would otherwise be blank, we fall back to frequent tags
(the most common tags on the current page of results).
Also change it so that if Reportbooru is unconfigured, we fail
gracefully by returning blank results instead of failing with an
exception. This is so we can still view the popular searches and missed
searches pages during testing (even though they'll be blank).
* Combine MissedSearchService, PostViewCountService, and
PopularSearchService into single ReportbooruService class.
* Use Danbooru::Http for these services instead of HTTParty.
Hide banned artist pages from anonymous (logged out) users. Partial
revert of 6b066f2ca. Artists sometimes ask us to remove all their
information from the site, including their artist profile. It's easier
to hide their profile than to explain to Japanese artists that a) we're
under no obligation to remove their profile and b) we need to keep it to
maintain the ban on their content that they asked for.
Reduce indirection. PostSet is basically a collection of helper methods
for rendering the post index page. PostSetPresenter was a set of helper
methods for rendering the tag list on the post index page. These don't
need to be separated.
Make PostQueryBuilder apply aliases earlier, immediately after parsing
the search.
On the post index page there are multiple places where we need to apply
aliases:
* When running the search with PostQueryBuilder#build.
* When calculating the search count with PostQueryBuilder#fast_count.
* When calculating the related tags for the sidebar.
* When tracking missed searches and popular searches for Reportbooru.
* When looking up wiki excerpts.
Applying aliases after parsing ensures we only have to apply aliases
once for all of these things.
We also normalize the order of tags in searches and strip repeated tags.
This is so that we have consistent cache keys for fast_count.
* Fixes searches for aliased tags being counted as missed searches (fixes#4433).
* Fixes wiki excerpts not showing up when searching for aliased tags.
* Add unaliased:<tag> metatag. This allows you to search for a tag
without applying aliases. This is mainly useful for debugging purposes
and for searching for large tags that are in the process of being
aliased but haven't had all their posts moved yet.
* Remove the "raw" url param from the posts index page. The "raw" param
also caused the search to ignore aliases, but it was undocumented and
exploitable. It was possible to use the raw param to view private
favorites since favorites are treated like a hidden tag.