immich
immich copied to clipboard
feat: loading screen, initSDK on bootstrap, fix FOUC for theme
This adds a loading screen, which is just the spinner right now. This will be shown while all the .js and .css resources are being loaded. It will only show after .3 seconds, to prevent a flicker for quickly loading apps (previously cached) but will still show some loading indicator for slower starts (first time, slow network, etc)
The theme initialization code was rewritten to be a little clearer, and a little more efficient. There appeared to handling to 'upgrade' the format of an old theme key in localstorage (which was just a string) to a json object - I left this in for now, but probably can remove in near future.
The "default" theme, when the app has never been loaded before (no localstorage) is now light, but use system prefs, instead of dark, don't use system prefs. This is probably closer to what people would want - but this could go back to dark-by default.
Fix: The "dark" class was removed from the "html" element, since it was set/unset on the document element by the theme changer.
Fix: FOUC still happened because the tailwind css doesn't get loaded until much later - and on slow connections or initial loads, this is obvious. So, to fix that, I added some minimal inline styles so that the background would at least be styled before tailwind loads.
The same styles names are used, but they appear early in the DOM tree, so that when tailscale loads, injecting the stylesheet at the end of the <head> element, it will override the earlier css declarations.
Additionally, the loading spinner was added as a inline-svg, as well as the animation css to make it spin. This spinner is removed by the root +layout.svelte during onMount().
Thoughts: The spinner is 1300 bytes - the immich logo is ~1900 bytes - perhaps we could use the immich logo (pulsating?) as a load screen?
Changes in root +layout.ts and +page.ts - it appears that svelte races all the load functions: so either +layout .load() and +page .load() will run in parallel. Technically, layout.load() will run first, but if it starts to await an async method, the +page.ts load() will start to run. To that end, I refactored the initialization of the SDK (setting defaults.fetch) into a shared function, and I call it from both load functions. I also wrap all the initializers of the layout load() function in a try/catch, because if the layout itself throws an error, then the error page can not be shown, since the error page also requires the layout. Instead, save the error in the page data object, and display it in the layout. I also moved the loadConfig() function from the layout mount to be in the layout load() since that really is a non-template loader, and it should not be part of the layout component - it really does belong in the load function.
Future work - the page load() function uses the $t() localized string lookup, but the layout load() is the place where it is initialized. If you call $t() before calling init(), the svelte-18n throws. It would be nice to have a single util that can do all of the bootstrap initialization can be performed - and it would be invoked by both the page and layout load() functions, and can lead to some performance improvements - since layout calls "loadConfig()" and page calls "getServerConfig()" which end up calling that same endpoint twice during startup.
This PR conflicts with #10335, correct?
Thanks, @midzelis, for the PR; I just tried to run the PR, and I like it! I have some thoughts.
- I'd like to have the default theme not be a system theme because it hides the change color theme button on the app bar.
-
Thoughts: The spinner is 1300 bytes - the immich logo is ~1900 bytes - perhaps we could use the immich logo (pulsating?) as a load screen?
I think the pulsating Immich logo would be better.
The last commit adds the immich logo instead of spinner. Using a pulsing effect, which an expanding drop shadow filter, and slightly expanding logo, which looks kinda cool - but I'm not an artist.
@alextran1502 I see what your saying about defaulting to system - it does hide the theme chooser in the bar. I agree it should be there by default.
Instead, what if - don't set a preference at all at bootstrap - just read it, and use it if present. However, if it isn't present, choose the default system color (dark/light) - but don't save it. Because its not saved, the default behavior of the theme chooser is to show up. That means you will see dark if you're system is dark, but you also see the theme chooser. Likewise, if your system is light, you'll see light, and the chooser.
When you go to preference, you'll see that system is unchecked. The next time you change that preference in settings, or if you flip the theme from dark/light - that will be persisted in local storage.
This is a compromise, and I think its a pretty decent "default" behavior, but if you want it to be light/not system by default, thats easy too - just a single line of code.
https://github.com/immich-app/immich/assets/13544796/56412c19-5237-4704-b5e3-d1375cc7ffc2
https://github.com/immich-app/immich/assets/13544796/dbbd7ac2-d50a-4f6d-98ca-218cf19e4715