FontLoader: Overhaul
This commit is contained in:
parent
4b2c093346
commit
359503153e
2 changed files with 54 additions and 50 deletions
|
|
@ -6,12 +6,16 @@
|
|||
|
||||
import "./styles.css";
|
||||
|
||||
import { definePluginSettings, migratePluginSetting } from "@api/Settings";
|
||||
import { isPluginEnabled } from "@api/PluginManager";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { managedStyleRootNode } from "@api/Styles";
|
||||
import { Button } from "@components/Button";
|
||||
import { Card } from "@components/Card";
|
||||
import { HeadingSecondary, HeadingTertiary } from "@components/Heading";
|
||||
import { Paragraph } from "@components/Paragraph";
|
||||
import { debounce } from "@shared/debounce";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { createAndAppendStyle } from "@utils/css";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
|
@ -32,13 +36,8 @@ interface GoogleFontMetadata {
|
|||
}>;
|
||||
}
|
||||
|
||||
const createGoogleFontUrl = (family: string, options = "") =>
|
||||
`https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}${options}&display=swap`;
|
||||
|
||||
const loadFontStyle = (url: string) => {
|
||||
document.head.insertAdjacentHTML("beforeend", `<link rel="stylesheet" href="${url}">`);
|
||||
return document.createElement("style");
|
||||
};
|
||||
const fontImport = (family: string, weights: string) =>
|
||||
`@import url("https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:wght@${weights}&display=swap");`;
|
||||
|
||||
async function searchGoogleFonts(query: string) {
|
||||
try {
|
||||
|
|
@ -70,47 +69,35 @@ async function searchGoogleFonts(query: string) {
|
|||
}
|
||||
}
|
||||
|
||||
const preloadFont = (family: string) =>
|
||||
loadFontStyle(createGoogleFontUrl(family, ":wght@400;700"));
|
||||
let fontStyle: HTMLStyleElement | null = null;
|
||||
|
||||
let styleElement: HTMLStyleElement | null = null;
|
||||
|
||||
const applyFont = async (fontFamily: string) => {
|
||||
function applyFont(fontFamily: string) {
|
||||
if (!fontFamily) {
|
||||
styleElement?.remove();
|
||||
styleElement = null;
|
||||
fontStyle?.remove();
|
||||
fontStyle = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!styleElement) {
|
||||
styleElement = document.createElement("style");
|
||||
document.head.appendChild(styleElement);
|
||||
fontStyle ??= createAndAppendStyle("vc-fontloader", managedStyleRootNode);
|
||||
fontStyle.textContent = `
|
||||
${fontImport(fontFamily, "300;400;500;600;700")}
|
||||
* {
|
||||
--font-primary: '${fontFamily}', sans-serif !important;
|
||||
--font-display: '${fontFamily}', sans-serif !important;
|
||||
--font-headline: '${fontFamily}', sans-serif !important;
|
||||
${settings.store.applyOnCodeBlocks ? `--font-code: '${fontFamily}', monospace !important;` : ""}
|
||||
}
|
||||
|
||||
loadFontStyle(createGoogleFontUrl(fontFamily, ":wght@300;400;500;600;700"));
|
||||
styleElement.textContent = `
|
||||
* {
|
||||
--font-primary: '${fontFamily}', sans-serif !important;
|
||||
--font-display: '${fontFamily}', sans-serif !important;
|
||||
--font-headline: '${fontFamily}', sans-serif !important;
|
||||
${settings.store.applyOnCodeBlocks ? "--font-code: '${fontFamily}', monospace !important;" : ""}
|
||||
}
|
||||
`;
|
||||
} catch (err) {
|
||||
console.error("Failed to load font:", err);
|
||||
}
|
||||
};
|
||||
`;
|
||||
}
|
||||
|
||||
function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) => void; }) {
|
||||
const [query, setQuery] = React.useState("");
|
||||
const [results, setResults] = React.useState<GoogleFontMetadata[]>([]);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const previewStyles = React.useRef<HTMLStyleElement[]>([]);
|
||||
const previewStyle = React.useRef<HTMLStyleElement | null>(null);
|
||||
const { selectedFont } = settings.use(["selectedFont"]);
|
||||
|
||||
React.useEffect(() => () => {
|
||||
previewStyles.current.forEach(style => style.remove());
|
||||
}, []);
|
||||
React.useEffect(() => () => previewStyle.current?.remove(), []);
|
||||
|
||||
const debouncedSearch = debounce(async (value: string) => {
|
||||
setLoading(true);
|
||||
|
|
@ -121,8 +108,8 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
|||
}
|
||||
|
||||
const fonts = await searchGoogleFonts(value);
|
||||
previewStyles.current.forEach(style => style.remove());
|
||||
previewStyles.current = await Promise.all(fonts.map(f => preloadFont(f.family)));
|
||||
previewStyle.current ??= createAndAppendStyle("vc-fontloader-previews", managedStyleRootNode);
|
||||
previewStyle.current.textContent = fonts.map(f => fontImport(f.family, "400;700")).join("\n");
|
||||
setResults(fonts);
|
||||
setLoading(false);
|
||||
}, 300);
|
||||
|
|
@ -137,6 +124,22 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
|||
<HeadingSecondary>Search Google Fonts</HeadingSecondary>
|
||||
<Paragraph className={Margins.bottom8}>Click on any font to apply it.</Paragraph>
|
||||
|
||||
{selectedFont && (
|
||||
<div className={classes(Margins.bottom8, "eq-googlefonts-current")}>
|
||||
<Paragraph>Current font: <strong>{selectedFont}</strong></Paragraph>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
settings.store.selectedFont = "";
|
||||
applyFont("");
|
||||
}}
|
||||
>
|
||||
Reset Font
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<TextInput
|
||||
value={query}
|
||||
onChange={e => handleSearch(e)}
|
||||
|
|
@ -169,7 +172,6 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
|||
);
|
||||
}
|
||||
|
||||
migratePluginSetting("FontLoader", "applyOnCodeBlocks", "applyOnClodeBlocks");
|
||||
const settings = definePluginSettings({
|
||||
selectedFont: {
|
||||
type: OptionType.STRING,
|
||||
|
|
@ -184,7 +186,7 @@ const settings = definePluginSettings({
|
|||
<GoogleFontSearch
|
||||
onSelect={font => {
|
||||
settings.store.selectedFont = font.family;
|
||||
applyFont(font.family);
|
||||
if (isPluginEnabled("FontLoader")) applyFont(font.family);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
@ -203,17 +205,11 @@ export default definePlugin({
|
|||
authors: [EquicordDevs.vmohammad],
|
||||
settings,
|
||||
|
||||
async start() {
|
||||
const savedFont = settings.store.selectedFont;
|
||||
if (savedFont) {
|
||||
await applyFont(savedFont);
|
||||
}
|
||||
start() {
|
||||
applyFont(settings.store.selectedFont);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (styleElement) {
|
||||
styleElement.remove();
|
||||
styleElement = null;
|
||||
}
|
||||
applyFont("");
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
.eq-googlefonts-current {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.eq-googlefonts-results {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.eq-googlefonts-card {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue