Skip to content

Commit

Permalink
feat(libs): fontsource api, font selector
Browse files Browse the repository at this point in the history
  • Loading branch information
crashmax-dev committed Dec 16, 2023
1 parent acb0c71 commit f3c12df
Show file tree
Hide file tree
Showing 15 changed files with 449 additions and 435 deletions.
5 changes: 3 additions & 2 deletions frontend/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@tabler/icons-vue": "^2.44.0",
"@tanstack/query-broadcast-client-experimental": "^4.36.1",
"@tanstack/vue-query": "^4.37.0",
"@twir/fontsource": "workspace:^",
"@twir/frontend-chat": "workspace:^",
"@twir/grpc": "workspace:^",
"@types/lodash.chunk": "^4.2.9",
Expand All @@ -25,10 +26,10 @@
"grid-layout-plus": "^1.0.3",
"kappagen": "^0.3.5",
"lodash.chunk": "^4.2.0",
"naive-ui": "^2.35.0",
"naive-ui": "2.35.0",
"nested-css-to-flat": "^1.0.5",
"plyr": "^3.7.8",
"vue": "^3.3.11",
"vue": "3.3.12",
"vue-draggable-next": "^2.2.1",
"vue-i18n": "^9.8.0",
"vue-router": "^4.2.5",
Expand Down
71 changes: 10 additions & 61 deletions frontend/dashboard/src/pages/overlays/chat/Chat.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { IconReload } from '@tabler/icons-vue';
import { FontSelector } from '@twir/fontsource';
import {
ChatBox,
type Message,
Expand All @@ -17,8 +17,6 @@ import {
NSwitch,
NSlider,
NSelect,
NTreeSelect,
type TreeSelectOption,
useThemeVars,
NDivider,
NColorPicker,
Expand All @@ -31,30 +29,27 @@ import * as faker from './faker.js';
import {
useChatOverlayManager,
useGoogleFontsList,
useProfile,
useUserAccessFlagChecker,
} from '@/api/index.js';
import { useCopyOverlayLink } from '@/components/overlays/copyOverlayLink';
const chatManager = useChatOverlayManager();
const {
data: settings,
isLoading: isSettingsLoading,
isError: isSettingsError,
} = chatManager.getSettings();
const updater = chatManager.updateSettings();
const {
data: googleFonts,
isError: isGoogleFontsError,
isLoading: isGoogleFontsLoading,
} = useGoogleFontsList();
const themeVars = useThemeVars();
const globalBadgesObject = Object.fromEntries(globalBadges);
const messagesMock = ref<Message[]>([]);
useIntervalFn(() => {
const internalId = crypto.randomUUID();
Expand Down Expand Up @@ -85,17 +80,16 @@ useIntervalFn(() => {
}
}, 1 * 1000);
const defaultFont = 'Roboto:700italic';
const defaultSettings: Settings = {
fontFamily: 'roboto',
fontSize: 20,
// fontWeight: 400,
// fontItalic: false,
hideBots: false,
hideCommands: false,
messageHideTimeout: 0,
messageShowDelay: 0,
preset: 'clean',
fontFamily: defaultFont,
showBadges: true,
showAnnounceBadge: true,
reverseMessages: false,
Expand Down Expand Up @@ -146,22 +140,6 @@ const styleSelectOptions = [
{ label: 'Boxed', value: 'boxed' },
];
const fontSelectOptions = computed<TreeSelectOption[]>(() => {
return googleFonts?.value?.fonts
.map((f) => {
const option: TreeSelectOption = {
label: f.family,
children: f.files.map((c) => ({
label: `${f.family}:${c.name}`,
key: `${f.family}:${c.name}`,
})),
key: f.family,
};
return option;
}) ?? [];
});
const setDefaultSettings = () => {
formValue.value = structuredClone(defaultSettings);
};
Expand Down Expand Up @@ -235,38 +213,9 @@ const canCopyLink = computed(() => {

<n-divider />

<div style="display: flex; flex-direction: column; gap: 4px;">
<div style="display: flex; justify-content: space-between;">
<span>{{ t('overlays.chat.fontFamily') }}</span>
<n-button
size="tiny" secondary type="success"
@click="formValue.fontFamily = defaultFont"
>
<IconReload style="height: 15px;" />
{{ t('overlays.chat.resetToDefault') }}
</n-button>
</div>

<n-tree-select
v-model:value="formValue.fontFamily"
filterable
:options="fontSelectOptions"
:loading="isGoogleFontsLoading"
:disabled="isGoogleFontsError"
check-strategy="child"
>
<template #action>
{{ t('overlays.chat.fontFamilyDescription') }}
<a
class="action-link"
href="https://fonts.google.com/"
target="_blank"
:style="{ color: themeVars.successColor }"
>
Preview Google Fonts
</a>
</template>
</n-tree-select>
<div>
<span>{{ t('overlays.chat.fontFamily') }}</span>
<font-selector initial-font-family="roboto" @update-font-family="console.log" />
</div>

<div class="slider">
Expand Down
2 changes: 1 addition & 1 deletion frontend/landing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"ioredis": "5.3.2",
"nanostores": "0.9.5",
"tailwindcss": "3.3.6",
"vue": "3.3.10"
"vue": "3.3.12"
},
"devDependencies": {
"@types/node": "20.10.3",
Expand Down
2 changes: 1 addition & 1 deletion frontend/overlays/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"nested-css-to-flat": "1.0.5",
"obs-websocket-js": "5.0.3",
"tmi.js": "1.8.5",
"vue": "3.3.9",
"vue": "3.3.12",
"vue-router": "4.2.5"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion frontend/public-page/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@twir/grpc": "workspace:^",
"@vueuse/components": "10.6.1",
"@vueuse/core": "10.6.1",
"vue": "3.3.9",
"vue": "3.3.12",
"vue-router": "4.2.5"
},
"devDependencies": {
Expand Down
12 changes: 12 additions & 0 deletions libs/fontsource/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "@twir/fontsource",
"type": "module",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"naive-ui": "2.35.0",
"vue": "3.3.12"
}
}
56 changes: 56 additions & 0 deletions libs/fontsource/src/components/font-selector.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script setup lang="ts">
import type { SelectOption } from 'naive-ui';
import { NSelect } from 'naive-ui';
import { ref, computed, watch, h } from 'vue';
import { useFontSource } from '../composable/use-fontsource.js';
const props = defineProps<{
initialFontFamily: string
}>();
const emits = defineEmits<{
'update-font-family': [fontFamily: string]
}>();
const fontSource = useFontSource();
const selectedFont = ref(props.initialFontFamily);
watch(() => selectedFont.value, async (font) => {
if (!font || fontSource.loading.value) return;
await fontSource.loadFont(font);
emits('update-font-family', font);
});
const options = computed((): SelectOption[] => {
return fontSource.fonts.value.map((font) => ({
label: font.family,
value: font.id,
}));
});
function renderLabel(option: SelectOption) {
if (!fontSource.loading.value) {
fontSource.loadFont(option.value as string);
}
return h(
'div',
{ style: { 'font-family': `"${option.value}"` } },
{ default: () => option.label },
);
}
</script>

<template>
<n-select
v-model:value="selectedFont"
:default-value="props.initialFontFamily"
:render-label="renderLabel"
filterable
:options="options"
:loading="fontSource.loading.value"
:disabled="fontSource.loading.value"
check-strategy="child"
/>
</template>
37 changes: 37 additions & 0 deletions libs/fontsource/src/composable/use-fontsource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ref, onMounted } from 'vue';

import { loadFontItems, loadFont as loadFontById } from '../helpers.js';
import type { FontItem } from '../types.js';

export function useFontSource() {
const loading = ref(true);
const fonts = ref<FontItem[]>([]);

onMounted(async () => {
try {
fonts.value = await loadFontItems();
} catch (err) {
console.error(err);
} finally {
loading.value = false;
}
});

async function loadFont(fontId: string, fontWeight = 400) {
for (const fontFace of document.fonts.values()) {
if (fontFace.family === fontId) return;
}

try {
await loadFontById(fontId, fontWeight);
} catch (err) {
console.error(err);
}
}

return {
loading,
fonts,
loadFont,
};
}
1 change: 1 addition & 0 deletions libs/fontsource/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const FONTSOURCE_API_URL = 'https://api.fontsource.org/v1';
20 changes: 20 additions & 0 deletions libs/fontsource/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FONTSOURCE_API_URL } from './constants.js';
import type { Font, FontItem } from './types.js';

export async function loadFontItems() {
const response = await fetch(`${FONTSOURCE_API_URL}/fonts`);
const fonts = await response.json() as FontItem[];
return fonts;
}

export async function loadFont(fontId: string, fontWeight = 400) {
const response = await fetch(`${FONTSOURCE_API_URL}/fonts/${fontId}`);
const font = await response.json() as Font;

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const fontSource = `url(${font.variants[fontWeight].normal.latin.url.woff2})`;
const fontFace = new FontFace(font.id, fontSource);
await fontFace.load();
document.fonts.add(fontFace);
}
7 changes: 7 additions & 0 deletions libs/fontsource/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import FontSelector from './components/font-selector.vue';
import { useFontSource } from './composable/use-fontsource.js';

export {
FontSelector,
useFontSource,
};
57 changes: 57 additions & 0 deletions libs/fontsource/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export type FontVariants =
| '100'
| '200'
| '300'
| '400'
| '500'
| '600'
| '700'
| '800'
| '900'

export type FontStyle = 'normal' | 'italic'
export type FontSubset = 'latin' | 'cyrillic'
export type FontType = 'woff2'

export interface FontItem {
category: string
defSubset: string
family: string
id: string
lastModified: string
styles: FontStyle[]
subsets: FontSubset[]
type: string
variable: boolean
version: string
weights: number[]
}

export type FontVariant = {
[key in FontVariants]: {
[key in FontStyle]: {
[key in FontSubset]: {
url: {
[key in FontType]: string
}
}
}
}
}

export interface Font {
id: string
family: string
subsets: FontSubset
weights: number[]
styles: string[]
unicodeRange: {
[key in FontSubset]: string
}
defSubset: string
variable: boolean
category: string
version: string
type: string
variants: FontVariant
}
Loading

0 comments on commit f3c12df

Please sign in to comment.