From fa4320556938cfd1051d10409bc1815222965ce3 Mon Sep 17 00:00:00 2001 From: "Kilu.He" <108015703+qinluhe@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:08:16 +0800 Subject: [PATCH] fix: suppot display icon on helmet (#26) --- deploy/server.ts | 51 +++++++++++++++++-- src/components/_shared/helmet/ViewHelmet.tsx | 41 ++++++++++----- .../grid/grid-column/GridColumn.tsx | 6 +-- src/utils/emoji.ts | 31 ++++++----- 4 files changed, 97 insertions(+), 32 deletions(-) diff --git a/deploy/server.ts b/deploy/server.ts index db79e5c..f3d2b9d 100644 --- a/deploy/server.ts +++ b/deploy/server.ts @@ -47,7 +47,7 @@ const fetchMetaData = async (namespace: string, publishName?: string) => { let url = `${baseURL}/api/workspace/published/${namespace}`; if (publishName) { - url += `/${publishName}`; + url = `${baseURL}/api/workspace/v1/published/${namespace}/${publishName}`; } logger.info(`Fetching meta data from ${url}`); @@ -60,7 +60,11 @@ const fetchMetaData = async (namespace: string, publishName?: string) => { throw new Error(`HTTP error! Status: ${response.status}`); } - return response.json(); + const data = await response.json(); + + logger.info(`Fetched meta data from ${url}: ${JSON.stringify(data)}`); + + return data; } catch (error) { logger.error(`Error fetching meta data ${error}`); return null; @@ -130,7 +134,11 @@ const createServer = async (req: Request) => { const data = await fetchMetaData(namespace, publishName); if (publishName) { - metaData = data; + if (data.code === 0) { + metaData = data.data; + } else { + logger.error(`Error fetching meta data: ${JSON.stringify(data)}`); + } } else { const publishInfo = data?.data?.info; @@ -165,6 +173,7 @@ const createServer = async (req: Request) => { if (metaData && metaData.view) { const view = metaData.view; const emoji = view.icon?.ty === 0 && view.icon?.value; + const icon = view.icon?.ty === 2 && view.icon?.value; const titleList = []; if (emoji) { @@ -172,6 +181,15 @@ const createServer = async (req: Request) => { const baseUrl = 'https://raw.githubusercontent.com/googlefonts/noto-emoji/main/svg/emoji_u'; favicon = `${baseUrl}${emojiCode}.svg`; + } else if (icon) { + try { + const { iconContent, color } = JSON.parse(view.icon?.value); + + favicon = getIconBase64(iconContent, color); + $('link[rel="icon"]').attr('type', 'image/svg+xml'); + } catch (_) { + // Do nothing + } } if (view.name) { @@ -253,3 +271,30 @@ const start = () => { start(); export {}; + +function getIconBase64 (svgText: string, color: string) { + let newSvgText = svgText.replace(/fill="[^"]*"/g, ``); + + newSvgText = newSvgText.replace(' { try { let url = '/appflowy.svg'; - - if (icon && icon.ty === ViewIconType.Emoji && icon.value) { - const emojiCode = icon?.value?.codePointAt(0)?.toString(16); // Convert emoji to hex code - const baseUrl = 'https://raw.githubusercontent.com/googlefonts/noto-emoji/main/svg/emoji_u'; - - const response = await fetch(`${baseUrl}${emojiCode}.svg`); - const svgText = await response.text(); - const blob = new Blob([svgText], { type: 'image/svg+xml' }); - - url = URL.createObjectURL(blob); - } - const link = document.querySelector('link[rel*=\'icon\']') as HTMLLinkElement || document.createElement('link'); - link.type = 'image/svg+xml'; + if (icon && icon.value) { + if (icon.ty === ViewIconType.Emoji) { + const emojiCode = icon?.value?.codePointAt(0)?.toString(16); // Convert emoji to hex code + const baseUrl = 'https://raw.githubusercontent.com/googlefonts/noto-emoji/main/svg/emoji_u'; + + const response = await fetch(`${baseUrl}${emojiCode}.svg`); + const svgText = await response.text(); + const blob = new Blob([svgText], { type: 'image/svg+xml' }); + + url = URL.createObjectURL(blob); + + link.type = 'image/svg+xml'; + + } else if (icon.ty === ViewIconType.Icon) { + const { + groupName, + iconName, + color, + } = JSON.parse(icon.value); + const id = `${groupName}/${iconName}`; + + url = (await getIconBase64(id, color)) || ''; + link.type = 'image/svg+xml'; + } + + } + link.rel = 'icon'; link.href = url; document.getElementsByTagName('head')[0].appendChild(link); diff --git a/src/components/database/components/grid/grid-column/GridColumn.tsx b/src/components/database/components/grid/grid-column/GridColumn.tsx index e3f538c..ba0adc0 100644 --- a/src/components/database/components/grid/grid-column/GridColumn.tsx +++ b/src/components/database/components/grid/grid-column/GridColumn.tsx @@ -3,7 +3,7 @@ import { FieldType } from '@/application/database-yjs/database.type'; import { Column, useFieldSelector } from '@/application/database-yjs/selector'; import { FieldTypeIcon } from '@/components/database/components/field'; import { ThemeModeContext } from '@/components/main/useAppThemeMode'; -import { getIconSvgEncodedContent } from '@/utils/emoji'; +import { getIconBase64 } from '@/utils/emoji'; import { Tooltip } from '@mui/material'; import React, { useContext, useEffect, useMemo, useState } from 'react'; import { ReactComponent as AIIndicatorSvg } from '@/assets/ai_indicator.svg'; @@ -25,8 +25,8 @@ export function GridColumn ({ column, index }: { column: Column; index: number } useEffect(() => { if (icon) { - void getIconSvgEncodedContent(icon, isDark ? 'white' : 'black').then((res) => { - setIconEncodeContent(res); + void getIconBase64(icon, isDark ? 'white' : 'black').then((res) => { + if (res) setIconEncodeContent(res); }); } }, [icon, isDark]); diff --git a/src/utils/emoji.ts b/src/utils/emoji.ts index 7828209..2da159d 100644 --- a/src/utils/emoji.ts +++ b/src/utils/emoji.ts @@ -1,7 +1,8 @@ +import { renderColor } from '@/utils/color'; import { EmojiMartData } from '@emoji-mart/data'; import axios from 'axios'; -export async function randomEmoji(skin = 0) { +export async function randomEmoji (skin = 0) { const emojiData = await loadEmojiData(); const emojis = (emojiData as EmojiMartData).emojis; const keys = Object.keys(emojis); @@ -10,11 +11,11 @@ export async function randomEmoji(skin = 0) { return emojis[randomKey].skins[skin].native; } -export async function loadEmojiData() { +export async function loadEmojiData () { return import('@emoji-mart/data/sets/15/native.json'); } -export function isFlagEmoji(emoji: string) { +export function isFlagEmoji (emoji: string) { return /\uD83C[\uDDE6-\uDDFF]/.test(emoji); } @@ -45,7 +46,7 @@ let icons: Record | undefined; -export async function loadIcons(): Promise< +export async function loadIcons (): Promise< Record< ICON_CATEGORY, { @@ -66,20 +67,24 @@ export async function loadIcons(): Promise< }); } -export async function getIconSvgEncodedContent(id: string, color: string) { +export async function getIconBase64 (id: string, color: string) { try { - const { data } = await axios.get(`/af_icons/${id}.svg`); + const response = await fetch(`/af_icons/${id}.svg`); + let svgText = await response.text(); - const urlEncodedContent = encodeURIComponent(data.replaceAll('black', color)); + svgText = svgText.replace(/fill="[^"]*"/g, ``); + svgText = svgText.replace('