mirror of
https://github.com/discourse/discourse.git
synced 2025-03-04 18:29:20 +00:00
The dots in the splash were previously hard-coded (v1). This PR makes progress towards making them be based on current theme colors. Note that this is an improvement and not the "final" version. We're going to dynamically generate the splash file and the base64 URL later on.
285 lines
7.4 KiB
Plaintext
285 lines
7.4 KiB
Plaintext
<%- unless customization_disabled? %>
|
|
<section id="d-splash">
|
|
<template class="splash-svg-template">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
version="1.1"
|
|
>
|
|
<style>
|
|
:root {
|
|
--animation-state: paused;
|
|
--primary: #<%= ColorScheme.hex_for_name("primary", scheme_id) %>;
|
|
--secondary: #<%= ColorScheme.hex_for_name("secondary", scheme_id) %>;
|
|
--tertiary: #<%= ColorScheme.hex_for_name("tertiary", scheme_id) %>;
|
|
--quaternary: #<%= ColorScheme.hex_for_name("quaternary", scheme_id) %>;
|
|
--highlight: #<%= ColorScheme.hex_for_name("highlight", scheme_id) %>;
|
|
--success: #<%= ColorScheme.hex_for_name("success", scheme_id) %>;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--animation-state: paused;
|
|
--primary: #<%= ColorScheme.hex_for_name("primary", dark_scheme_id) %>;
|
|
--secondary: #<%= ColorScheme.hex_for_name(
|
|
"secondary",
|
|
dark_scheme_id
|
|
) %>;
|
|
--tertiary: #<%= ColorScheme.hex_for_name(
|
|
"tertiary",
|
|
dark_scheme_id
|
|
) %>;
|
|
--quaternary: #<%= ColorScheme.hex_for_name(
|
|
"quaternary",
|
|
dark_scheme_id
|
|
) %>;
|
|
--highlight: #<%= ColorScheme.hex_for_name(
|
|
"highlight",
|
|
dark_scheme_id
|
|
) %>;
|
|
--success: #<%= ColorScheme.hex_for_name("success", dark_scheme_id) %>;
|
|
}
|
|
}
|
|
|
|
/* these styles need to live here because the SVG has a different scope */
|
|
.dots {
|
|
animation-name: loader;
|
|
animation-timing-function: ease-in-out;
|
|
animation-duration: 3s;
|
|
animation-iteration-count: infinite;
|
|
animation-play-state: var(--animation-state);
|
|
stroke: #fff;
|
|
stroke-width: 0.5px;
|
|
transform-origin: center;
|
|
opacity: 0;
|
|
r: max(1vw, 11px);
|
|
cy: 50%;
|
|
filter: saturate(2) opacity(0.85);
|
|
}
|
|
|
|
.dots:first-child {
|
|
fill: var(--quaternary);
|
|
}
|
|
|
|
.dots:nth-child(2) {
|
|
fill: var(--quaternary);
|
|
animation-delay: 0.15s;
|
|
}
|
|
|
|
.dots:nth-child(3) {
|
|
fill: var(--highlight);
|
|
animation-delay: 0.3s;
|
|
}
|
|
|
|
.dots:nth-child(4) {
|
|
fill: var(--tertiary);
|
|
animation-delay: 0.45s;
|
|
}
|
|
|
|
.dots:nth-child(5) {
|
|
fill: var(--tertiary);
|
|
animation-delay: 0.6s;
|
|
}
|
|
|
|
@keyframes loader {
|
|
0% {
|
|
opacity: 0;
|
|
transform: scale(1);
|
|
}
|
|
45% {
|
|
opacity: 1;
|
|
transform: scale(0.7);
|
|
}
|
|
65% {
|
|
opacity: 1;
|
|
transform: scale(0.7);
|
|
}
|
|
100% {
|
|
opacity: 0;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<g class="container">
|
|
<circle class="dots" cx="30vw" />
|
|
<circle class="dots" cx="40vw" />
|
|
<circle class="dots" cx="50vw" />
|
|
<circle class="dots" cx="60vw" />
|
|
<circle class="dots" cx="70vw" />
|
|
</g>
|
|
</svg>
|
|
</template>
|
|
|
|
<style>
|
|
html {
|
|
overflow-y: hidden !important;
|
|
}
|
|
|
|
#d-splash {
|
|
display: grid;
|
|
place-items: center;
|
|
backface-visibility: hidden;
|
|
background: #<%= ColorScheme.hex_for_name("secondary", scheme_id) %>;
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
z-index: 1001;
|
|
--animation-state: paused;
|
|
}
|
|
|
|
#d-splash .preloader-image {
|
|
max-width: 100%;
|
|
height: 100vh;
|
|
}
|
|
|
|
#d-splash .preloader-text-wrapper {
|
|
position: absolute;
|
|
opacity: 0;
|
|
animation: fade-in 0.5s ease-in-out;
|
|
animation-delay: 1s;
|
|
animation-fill-mode: forwards;
|
|
animation-play-state: var(--animation-state);
|
|
color: #<%= ColorScheme.hex_for_name("primary", scheme_id) %>;
|
|
margin-bottom: -4em;
|
|
}
|
|
|
|
#d-splash .preloader-text:after {
|
|
animation: loading-text 3s infinite;
|
|
content: "";
|
|
position: absolute;
|
|
margin: 0 0.1em;
|
|
left: 100%;
|
|
}
|
|
|
|
.rtl #d-splash .preloader-text:after {
|
|
left: 0;
|
|
right: 100%;
|
|
}
|
|
|
|
@keyframes fade-in {
|
|
0% {
|
|
opacity: 0;
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes loading-text {
|
|
0% {
|
|
content: "";
|
|
}
|
|
25% {
|
|
content: ".";
|
|
}
|
|
50% {
|
|
content: "..";
|
|
}
|
|
75% {
|
|
content: "...";
|
|
}
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
#d-splash {
|
|
background: #<%= ColorScheme.hex_for_name("secondary", dark_scheme_id) %>;
|
|
}
|
|
#d-splash .preloader-text-wrapper {
|
|
color: #<%= ColorScheme.hex_for_name("primary", dark_scheme_id) %>;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<img
|
|
class="preloader-image"
|
|
src="data:image/svg;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
|
alt="<%=SiteSetting.title%>"
|
|
/>
|
|
|
|
<div class="preloader-text-wrapper">
|
|
<div class="preloader-text"><%= I18n.t("js.preloader_text") %></div>
|
|
</div>
|
|
|
|
<noscript>
|
|
<style>
|
|
html {
|
|
overflow-y: revert !important;
|
|
}
|
|
|
|
#d-splash {
|
|
display: none;
|
|
}
|
|
</style>
|
|
</noscript>
|
|
|
|
<script nonce="<%= ApplicationHelper.splash_screen_nonce %>">
|
|
const DELAY_TARGET = 2000;
|
|
const POLLING_INTERVAL = 50;
|
|
|
|
const splashSvgTemplate = document.querySelector(".splash-svg-template");
|
|
const splashTemplateClone = splashSvgTemplate.content.cloneNode(true);
|
|
const svgElement = splashTemplateClone.querySelector("svg");
|
|
|
|
const svgString = new XMLSerializer().serializeToString(svgElement);
|
|
const encodedSvg = btoa(svgString);
|
|
|
|
const splashWrapper = document.querySelector("#d-splash");
|
|
const splashImage = splashWrapper?.querySelector(".preloader-image");
|
|
|
|
if (splashImage) {
|
|
splashImage.src = `data:image/svg+xml;base64,${encodedSvg}`;
|
|
|
|
const connectStart = performance?.timing?.connectStart || 0;
|
|
const splashDelay = connectStart ? DELAY_TARGET : 0;
|
|
const targetTime = connectStart + DELAY_TARGET;
|
|
|
|
let splashInterval;
|
|
let discourseReady;
|
|
|
|
const swapSplash = () => {
|
|
splashWrapper?.style.setProperty("--animation-state", "running");
|
|
svgElement?.style.setProperty("--animation-state", "running");
|
|
|
|
const newSvgString = new XMLSerializer().serializeToString(svgElement);
|
|
const newEncodedSvg = btoa(newSvgString);
|
|
|
|
splashImage.src = `data:image/svg+xml;base64,${newEncodedSvg}`;
|
|
|
|
performance.mark("discourse-splash-visible");
|
|
|
|
clearSplashInterval();
|
|
};
|
|
|
|
const clearSplashInterval = () => {
|
|
clearInterval(splashInterval);
|
|
splashInterval = null;
|
|
};
|
|
|
|
(() => {
|
|
splashInterval = setInterval(() => {
|
|
if (discourseReady) {
|
|
clearSplashInterval();
|
|
}
|
|
|
|
if (Date.now() > targetTime) {
|
|
swapSplash();
|
|
}
|
|
}, POLLING_INTERVAL);
|
|
})();
|
|
|
|
document.addEventListener(
|
|
"discourse-ready",
|
|
() => {
|
|
discourseReady = true;
|
|
splashWrapper?.remove();
|
|
performance.mark("discourse-splash-removed");
|
|
},
|
|
{ once: true }
|
|
);
|
|
}
|
|
</script>
|
|
</section>
|
|
<%- end %>
|