mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-07 13:43:03 -04:00
feat(refactor): fontLoader (#148)
This commit is contained in:
parent
76c540bd73
commit
a0d0823def
1 changed files with 34 additions and 62 deletions
|
@ -13,6 +13,7 @@ import { Margins } from "@utils/margins";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Card, Forms, React, TextInput } from "@webpack/common";
|
import { Card, Forms, React, TextInput } from "@webpack/common";
|
||||||
|
|
||||||
interface GoogleFontMetadata {
|
interface GoogleFontMetadata {
|
||||||
family: string;
|
family: string;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
|
@ -27,7 +28,15 @@ interface GoogleFontMetadata {
|
||||||
}>;
|
}>;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
const userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome / 128.0.0.0 Safari / 537.36";
|
|
||||||
|
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");
|
||||||
|
};
|
||||||
|
|
||||||
async function searchGoogleFonts(query: string) {
|
async function searchGoogleFonts(query: string) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("https://fonts.google.com/$rpc/fonts.fe.catalog.actions.metadata.MetadataService/FontSearch", {
|
const response = await fetch("https://fonts.google.com/$rpc/fonts.fe.catalog.actions.metadata.MetadataService/FontSearch", {
|
||||||
|
@ -36,14 +45,12 @@ async function searchGoogleFonts(query: string) {
|
||||||
"content-type": "application/json+protobuf",
|
"content-type": "application/json+protobuf",
|
||||||
"x-user-agent": "grpc-web-javascript/0.1"
|
"x-user-agent": "grpc-web-javascript/0.1"
|
||||||
},
|
},
|
||||||
// the nulls are optional filters
|
|
||||||
body: JSON.stringify([[query, null, null, null, null, null, 1], [5], null, 16])
|
body: JSON.stringify([[query, null, null, null, null, null, 1], [5], null, 16])
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (!data?.[1]) return [];
|
if (!data?.[1]) return [];
|
||||||
// god please help me
|
return data[1].map(([_, fontData]: [string, any[]]) => ({
|
||||||
const fonts = data[1].map(([_, fontData]: [string, any[]]) => ({
|
|
||||||
family: fontData[0],
|
family: fontData[0],
|
||||||
displayName: fontData[1],
|
displayName: fontData[1],
|
||||||
authors: fontData[2],
|
authors: fontData[2],
|
||||||
|
@ -54,81 +61,52 @@ async function searchGoogleFonts(query: string) {
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
}));
|
}));
|
||||||
return fonts;
|
|
||||||
// LETS GO IT FUCKING WORKSSSSSSSSSSSS
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to fetch fonts:", err);
|
console.error("Failed to fetch fonts:", err);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function preloadFont(family: string) {
|
const preloadFont = (family: string) =>
|
||||||
// https://developers.google.com/fonts/docs/css2
|
loadFontStyle(createGoogleFontUrl(family, "&text=The quick brown fox jumps over the lazy dog"));
|
||||||
const url = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}&text=The quick brown fox jumps over the lazy dog&display=swap`;
|
|
||||||
const css = await fetch(url, {
|
|
||||||
headers: {
|
|
||||||
"User-Agent": userAgent
|
|
||||||
}
|
|
||||||
}).then(r => r.text());
|
|
||||||
|
|
||||||
const style = document.createElement("style");
|
let styleElement: HTMLStyleElement | null = null;
|
||||||
style.textContent = css;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function applyFont(fontFamily: string) {
|
const applyFont = async (fontFamily: string) => {
|
||||||
if (!fontFamily) {
|
if (!fontFamily) {
|
||||||
if (styleElement) {
|
styleElement?.remove();
|
||||||
styleElement.remove();
|
styleElement = null;
|
||||||
styleElement = null;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
|
||||||
`https://fonts.googleapis.com/css2?family=${encodeURIComponent(fontFamily)}:wght@300;400;500;600;700&display=swap`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"User-Agent": userAgent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const css = await response.text();
|
|
||||||
|
|
||||||
if (!styleElement) {
|
if (!styleElement) {
|
||||||
styleElement = document.createElement("style");
|
styleElement = document.createElement("style");
|
||||||
document.head.appendChild(styleElement);
|
document.head.appendChild(styleElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadFontStyle(createGoogleFontUrl(fontFamily, ":wght@300;400;500;600;700"));
|
||||||
styleElement.textContent = `
|
styleElement.textContent = `
|
||||||
${css}
|
* {
|
||||||
* {
|
--font-primary: '${fontFamily}', sans-serif !important;
|
||||||
--font-primary: '${fontFamily}', sans-serif !important;
|
--font-display: '${fontFamily}', sans-serif !important;
|
||||||
--font-display: '${fontFamily}', sans-serif !important;
|
--font-headline: '${fontFamily}', sans-serif !important;
|
||||||
--font-headline: '${fontFamily}', sans-serif !important;
|
--font-code: '${fontFamily}', monospace !important;
|
||||||
--font-code: '${fontFamily}', monospace !important;
|
}
|
||||||
}
|
`;
|
||||||
`;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to load font:", err);
|
console.error("Failed to load font:", err);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) => void; }) {
|
function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) => void; }) {
|
||||||
const [query, setQuery] = React.useState("");
|
const [query, setQuery] = React.useState("");
|
||||||
const [results, setResults] = React.useState<GoogleFontMetadata[]>([]);
|
const [results, setResults] = React.useState<GoogleFontMetadata[]>([]);
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
|
||||||
|
|
||||||
const previewStyles = React.useRef<HTMLStyleElement[]>([]);
|
const previewStyles = React.useRef<HTMLStyleElement[]>([]);
|
||||||
|
|
||||||
|
React.useEffect(() => () => {
|
||||||
React.useEffect(() => {
|
previewStyles.current.forEach(style => style.remove());
|
||||||
return () => {
|
|
||||||
previewStyles.current.forEach(style => style.remove());
|
|
||||||
};
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const debouncedSearch = debounce(async (value: string) => {
|
const debouncedSearch = debounce(async (value: string) => {
|
||||||
|
@ -138,22 +116,18 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fonts = await searchGoogleFonts(value);
|
const fonts = await searchGoogleFonts(value);
|
||||||
|
|
||||||
previewStyles.current.forEach(style => style.remove());
|
previewStyles.current.forEach(style => style.remove());
|
||||||
previewStyles.current = [];
|
previewStyles.current = await Promise.all(fonts.map(f => preloadFont(f.family)));
|
||||||
|
|
||||||
const styles = await Promise.all(fonts.map(f => preloadFont(f.family)));
|
|
||||||
previewStyles.current = styles;
|
|
||||||
|
|
||||||
setResults(fonts);
|
setResults(fonts);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
const handleSearch = React.useCallback((value: string) => {
|
const handleSearch = (e: string) => {
|
||||||
setQuery(value);
|
setQuery(e);
|
||||||
debouncedSearch(value);
|
debouncedSearch(e);
|
||||||
}, []);
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Forms.FormSection>
|
<Forms.FormSection>
|
||||||
|
@ -193,8 +167,6 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let styleElement: HTMLStyleElement | null = null;
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
selectedFont: {
|
selectedFont: {
|
||||||
type: OptionType.STRING,
|
type: OptionType.STRING,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue