Broken in 49bc2364 by the use of @extend.
Here's what happened. There are two CSS rules that both apply to pool links:
* a:link { color: var(--link-color); }
* .pool-category-series a { color: var(--series-pool-color); }
These rules have equal specificity (0-1-1). This means the rule that is
defined last takes priority. This means the order in which CSS files are
included matters. 49bc2364 used the @extend directive in a rule for
popup menus, which required an @import, which changed the order of the
CSS files, which made the a:link rule suddenly take priority over the
series pool rule.
The proper fix would be to use Sass's new @use directive instead of
@import, but that requires the latest version of Sass, which requires
the latest version of Webpacker, which we can't upgrade to yet because
of breaking changes.
The real moral of the story is: our CSS is very fragile because of
specificity rules. It's very important that rules are defined in a
certain order, otherwise our CSS will break.
* https://sass-lang.com/documentation/at-rules/use
* https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
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.
Change [quote] styling to Reddit/Github style (greyed out, with a bar on
the left side) instead of traditional forum style (big grey box around
the quote).
Reasons for this change:
* Box style is bulkier, especially for short quotes in comments.
* Box style works poorly for deeply nested quotes.
* Box style looks bad on widescreen monitors, since the quote stretches
across the full width of the screen.
* Add comment scores.
* Rework voting buttons so that you can click the upvote/downvote
buttons to toggle votes.
* Hide the edit, delete, undelete, and report buttons behind a popup menu.
* Show the upvote/downvote/reply buttons to logged out users. Redirect
them to the login page instead.
Previously thresholded comments were hidden completely. You had to click
the "Show X hidden comments" button to unhide all hidden comments in a
thread. Now it works like this:
* When a comment is below your threshold, the comment text is hidden and
replaced by a `[hidden]` link, which you can click to unhide the comment.
* When a comment is at half your threshold (for example, your threshold
is -8 but the comment is at -4), then the comment is greyed out.
This means that comments aren't completely hidden, they're just
collapsed, so you can see the commenter and the score without unhiding
the comment. It also means you don't have to scroll back up to unhide a
comment, and threads aren't disrupted by comments being secretly
hidden (which is confusing when people are replying to hidden comments,
which forces you to go back up and unhide to find).
The normalization always ends up being less than a pixels difference,
and the clamp applied later on removes that difference. Before the
clamp was added, it had the effect of moving the box along it's angle
of rotation. Now it moves it along the x,y axis of the image itself,
which is probably more intuitive anyways.
It's still needed for the drag and drop though, otherwise, it displaces
by a certain amount making it impossible to accurately place.
This option was originally added in issue #1747. But only ~350 users
ever disabled autocomplete, only ~120 of these were seen in the last
year, and only 9 new users who signed up in the last year disabled it.
Users wishing to disable autocomplete can use this CSS:
.ui-autocomplete { display: none !important: }
or this Javascript:
$("[data-autocomplete]").autocomplete("disable");
Remove the enable_post_navigation option. This option was originally
added to disable the next/prev post navbar beneath posts. It was later
repurposed to disable keyboard shortcuts.
Users who don't want keyboard shortcuts are advised to not press random
buttons on the keyboard like a caveman.
Only ~1200 users disabled this option and only ~600 were seen in the
last year.
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.
Display a red wavy underline beneath misspelled tags in autocomplete.
We use an inline image for the underline instead of the native
`text-decoration: red wavy underline` property because the native
underline is too big and ugly, and we have no way to adjust it. Making a
nice-looking wavy underline in CSS is surprisingly difficult. This
turned out to be the cleanest way.
* Add a frequently asked questions section.
* Add nicer looking upgrade buttons.
* Format the page nicer.
* Prevent users from attempting invalid upgrades on users that are
already Platinum or above.
This is the scenario:
* You type something in autocomplete, let's say 'touhou'.
* Autocomplete calls /autocomplete?search[query]=touhou&search[type]=tag_query
* The endpoint returns JSON, because the autocomplete call sets an
`Accept: application/json` header requesting JSON.
* Visit /autocomplete?search[query]=touhou&search[type]=tag_query in your browser.
* Notice that the cached JSON response is incorrectly returned, not an
HTML response like the browser requested.
The problem is that the response type is chosen based on the Accept
header, but the response didn't set the `Vary: Accept` header, so the
browser doesn't know the response type can vary and so it incorrectly
returns the cached response.
This issue is partially fixed by Rails 6.1 ([1]), which properly sets the
`Vary: Accept` header when the response depends on the Accept header.
However, the next issue is that Cloudflare doesn't respect the Vary
header at all ([2], [3]). Therefore we can't use the Accept header to
pick the format, instead we have explicitly specify the format with
/autocomplete.json.
This is clearer and better for caching anyway. Using the `Vary: Accept`
header reduces the cache hit rate, because the exact format of the
Accept header varies across browsers, which fragments the cache.
Whew.
[1] https://github.com/rails/rails/pull.36213
[2] https://community.cloudflare.com/t/cloudflare-cdn-cache-to-support-http-vary-header/160802
[3] https://support.cloudflare.com/hc/en-us/articles/115003206852
[4] https://www.smashingmagazine.com/2017/11/understanding-vary-header/
* Remove the `source` and `weight` html data attributes (no longer used).
* Make the `type` html data attribute properly indicate the completion
type. Valid types: `tag`, `tag-alias`, `tag-abbreviation`,
`tag-autocorrect`, `tag-other-name`.
* Set Max-Age= flag instead of Expires= flag.
* Set Secure flag when using HTTPS.
* Extend default cookie lifetime from 1 year to 20 years.
* Remove "session" expiration option (unused).
* Remove max cookie size check.
The cookie size check was previously added in #2518 to deal with running
out of space due to tag scripts and blacklists. This should no longer
happen since we no longer use cookies for these things. Remove the
warning because it should never happen, we can't fix it if it does, and
the user probably won't know how to fix it either.
* Let Mods and Admins see the email addresses of users below their level.
* Let users see their own email address on their profile.
* Let users verify or edit their email address from their profile.
This is to make catching sockpuppets easier, and to make it easier for
users to fix their email.
Add a new Owner user level for the site owner. Highly sensitive
operations like manually changing the passwords of other users will be
restricted to the site owner.
Display autocorrected tags similar to aliases, with an arrow pointing at
the corrected tag, but with a dotted underline beneath the misspelled
tag to indicate that it's misspelled.
This refactors the autocomplete Javascript to use a single dedicated
/autocomplete.json endpoint instead of a bunch of separate endpoints.
This simplifies the autocomplete Javascript by making it so that instead
of calling a different endpoint for each type of query (for users, wiki
pages, pools, artists, etc), then having to parse the results of each
call to get the data we need, we can call a single endpoint that returns
exactly what we need.
This also means we don't have to parse searches clientside in order to
autocomplete metatags. Instead we can just pass the search term to the
server and let it parse the search, which is easy to do serverside.
Finally, this makes autocomplete easier to test, and it makes it easier
to add more sophisticated autocomplete behavior, since most of the logic
lives serverside.
* 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.
Replace references to the `is_resolved` field with the `status` field.
Post flags were marked as resolved when a post was approved (but not
when the post was deleted because it went unapproved). The status field
supercedes the resolved field.