This clocks in a bit bigger than what Impress 2020 does in terms of
binary encoding (with gzip it's at 11K instead of 4K), but I'm okay
with that for the simplicity win.
Gonna try to swap this in for where we're still using Impress 2020 for
the species/color picker in the outfit editor!
I have some other changes planned too, but these are some easy ones. I
also turn back on this stuff in development, in hopes that my changes
can make these queries fast enough to not be a big deal anymore!
This hasn't worked for a while anyway! Let's remove the bits of code
where we deal with it, and the database field that signals it. (We also
make a corresponding change in Impress 2020, so it doesn't crash trying
to query based on the `prank` column.)
I also ran this snippet to clear out all the Nebula stuff in the db:
```rb
Color.transaction do
nebula = Color.where(prank: true).find_by_name("Nebula")
nebula.pet_types.includes(pet_states: :swf_assets).each do |pet_type|
pet_type.pet_states.each do |pet_state|
pet_state.parent_swf_asset_relationships.each do |psa|
psa.swf_asset.destroy!
psa.destroy!
end
pet_state.destroy!
end
pet_type.destroy!
end
nebula.destroy!
end
```
Now that we have such a convenient lil outfit viewer component we built
for the item page preview, it's easy peasy to drop it in here too! And
it's all nice and lightweight, since in this case it's basically just.
image tags, with some supporting enhancements.
Anyway, this page has no actual useful styles of its own yet. Gonna
make it look nice and such!
I'm experimenting with a Rainbow Pool ish UI, mainly as a support tool
for exploring and labeling poses—but one we can probably just show to
real users too!
Right now, I just use pet type images as a placeholder, and I polished
up some of the `pet_type_image` API. But we're probably gonna drop
these for a full outfit viewer, now that I think of it.
The silly motivation is that I wanted to remove `.prettierignore`,
which just exists to omit that one folder from `npm run format`. But it
also seems like this is the standard place to put them—a standard
created long after we first set this up lol
I forget what this was for, I think part of it was for managing item
names in different languages, and the "private" locale thing was
probably for WIP locales? But yeah, not used, delete!
Fun little bug: viewing the "Engulfed in Flames Effect" item was
showing our "502 Bad Gateway" custom error page in the embed. This is
because the Rails app was providing a `Content-Security-Policy` header
value that was longer than nginx is configured by default to allow, so
it was refusing the response, and showing the same 502 error as if the
app hadn't responded at all. (We discovered this by opening
`/var/log/nginx/error.log`, which explained this very clearly, ty~!)
In this change, we no longer list every `images.neopets.com` asset,
instead marking the entire domain as a valid image source for the
SWF asset embed iframe. I don't _love_ this solution, I liked the
property of specifying literally exactly the assets we allow! But I
don't think there's any practical danger here, and it helps a *lot* for
making this more reliable.
(If we could have solved this reliably by increasing nginx's allowed
response header size, I probably would've done that? But I researched a
bit, and ultimately concluded that I don't trust other intermediary
software like firewalls not to have the same issue. Let's not be
pushing the limits of HTTP headers of all things!)
I think this has just been broken for a long time? And I don't think
it's very useful in a world 15 years later, where our problem *used* to
be giant gaps in our library, which isn't really our data problem
anymore.
This was always modeling correctly, but not showing the message,
because Turbo doesn't handle anchors in redirect URLs the same way the
browser's full page loads do.
I forget why we had this as a `#` URL anyway to begin with. Use `?`
instead!
Oh oops, I forgot one of the kinds of restricted zones when refactoring
how we load search data in wardrobe-2020! This made most items with
restricted zones (like Be Gone items) not work correctly when you
search for them to add them to the item—though it *does* work correctly
when you reload the page or change the species, to get to load a
different way.
The basics are working great! There's a few known missing things though:
- Add reasonable noscript behavior
- Disable options where there's no valid appearance
- Lay it out actually _good_, instead of just images dumped there
Adapting what the Impress 2020 UI does, but in Ruby instead!
I feel like this is case is really starting to show the power of doing
this stuff in Rails instead of via an API… we can *really* take
advantage of our models and our handy idioms at all points. This is
just so much less *code* than this feature takes in Node + GraphQL +
React.
Oh, I didn't realize the `_elem` variant of these parts of the
`Content-Security-Policy` is newer, and so doesn't even work on my
current version of Safari on my Mac.
My rationale at the time was: `script_src_elem` is stricter against
things like imports, and I figured, ok let's do the strictest policy
that works. But since it's not fully compatible with browsers even
*I'm* using right now, and I'm not aware of an actual problem it would
prevent, let's back off that a bit! This should have the same effective
security properties for our case.
Note that the effect of this compatibility issue wasn't *weakening* the
policy; it was being *too* strict, by blocking the scripts and the
stylesheets. This is because `script_src_elem` was ignored, and
`script_src` was absent, so it fell back to `default_src none`.
Not using this on the item page preview yet, but we will!
I like this approach over e.g. a web component specifically for the
sandboxing: while I don't exactly *distrust* JS that we're loading from
Neopets.com, I don't like the idea of *any* part of the site that
executes arbitrary JS unsafely at runtime, even if we theoretically
trust where it theoretically came from. I don't want any failure
upstream to have effects on us!
I copied basically all of the JS from a related project
`impress-media-server` that I had spun up at one point, to investigate
similar embed techniques. Easy peasy drop-in-squeezy!
Also adapted from the Impress 2020 logic!
Note that I refactored `compatible_pet_type` to a series of scopes on
`PetType`. I think this is a simpler, clearer, and more flexible API!
This is a cute thing that I think sets us up for other stuff down the
line: move more of the outfit appearance logic into the `Outfit` class!
Now, we set up the item page with a temporary instance of `Outfit`,
then ask for its `visible_layers`.
Still missing restricted-zones logic and such, that's next!
Just stripping out the big React component, and having Rails output it!
There's a lot of work rn in extracting the Impress 2020 dependency from
the `wardrobe-2020` React app, and I'm just curious to see if we can
simplify it at all by pulling this stuff *way* back to basics, and
deleting the item page part of `wardrobe-2020` altogether.
In this draft, we regress a lot of functionality: it just shows the
item on a Blue Acara, with no ability to change it! I'm gonna play with
putting more of that back in.
I also haven't actually removed any of the item page React code; I just
stopped calling it. That can be a cleanup for another time, once we're
confident in this experiment!
Lmao I've been testing with an outfit that has all the kinds of items,
so I didn't notice that this new refactor to `@items[:dyeworks]` style
of tracking the items returns `nil` when there's none, instead of `[]`.
(I always make this mistake when I use `group_by` lmao sob)
In this change, we give the `@items` hash a default value, so that will
stop happening!
Previously, I added a Dyeworks section that was incorrect: the base
item being available in the NC Mall does *not* mean you can necessarily
dye it with a potion!
In this change, we lean on Owls to tell us more about Dyeworks status,
and only group items in this section that Owls has marked as "Permanent
Dyeworks".
We don't have support for limited-time Dyeworks items yet—I've sent out
a message asking the Owls team for more info on what they do for those
items!
I started writing this up, then sent a preview to a friend, and he was
like "oh cool, but also this is not correct?"
I didn't realize Dyeworks has limited-time support to be *able* to dye
certain items. Hey, glad we're writing this guide for people like me,
then! lol
I wonder if we can lean on Owls for this. It seems like they already
list "Permanent Dyeworks" for some items, I wonder if they say
something special for active limited-edition Dyeworks items!
Oh right, it's possible for `Item#pb?` to return true, but
`Item#pb_color` to return `nil`, if the item has the paintbrush item
description but we can't find a color whose name matches the item name.
This would be expected if a new color were added to Neopets, and PB
items for it were modeled by the community, but we hadn't manually
added the color to the database yet.
Previously, the Item Getting Guide would crash in this scenario. Now,
it correctly handles the possibility of a `nil` value for `pb_color`,
and shows some placeholder info.
To test this, I temporarily edited some item names to not contain the
color name anymore (e.g. "P-rate Elephante Shirt and Vest"), then
loaded the guide and made changes until it no longer crashed.
This doesn't matter a ton in production, where we already have most of
our manifests loaded! But it matters a lot on my relatively-fresh
development instance, at times like now when images.neopets.com is slow
to respond. A single item search was taking minutes before this change
(5 seconds of timeout per asset for 30 items!), but now takes a few
seconds the first time, as it should!