Initial commit
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { useAsyncEffect } from 'ahooks'
|
||||
import { appDefaultIconBackground } from '@/config'
|
||||
import { searchEmoji } from '@/utils/emoji'
|
||||
import type { AppIconType } from '@/types/app'
|
||||
|
||||
type UseAppFaviconOptions = {
|
||||
enable?: boolean
|
||||
icon_type?: AppIconType | null
|
||||
icon?: string
|
||||
icon_background?: string | null
|
||||
icon_url?: string | null
|
||||
}
|
||||
|
||||
export function useAppFavicon(options: UseAppFaviconOptions) {
|
||||
const {
|
||||
enable = true,
|
||||
icon_type = 'emoji',
|
||||
icon,
|
||||
icon_background,
|
||||
icon_url,
|
||||
} = options
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
if (!enable || (icon_type === 'image' && !icon_url) || (icon_type === 'emoji' && !icon))
|
||||
return
|
||||
|
||||
const isValidImageIcon = icon_type === 'image' && icon_url
|
||||
|
||||
const link: HTMLLinkElement = document.querySelector('link[rel*="icon"]') || document.createElement('link')
|
||||
|
||||
link.href = isValidImageIcon
|
||||
? icon_url
|
||||
: 'data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>'
|
||||
+ `<rect width=%22100%25%22 height=%22100%25%22 fill=%22${encodeURIComponent(icon_background || appDefaultIconBackground)}%22 rx=%2230%22 ry=%2230%22 />`
|
||||
+ `<text x=%2212.5%22 y=%221em%22 font-size=%2275%22>${icon ? await searchEmoji(icon) : '🤖'
|
||||
}</text>`
|
||||
+ '</svg>'
|
||||
|
||||
link.rel = 'shortcut icon'
|
||||
link.type = 'image/svg'
|
||||
document.getElementsByTagName('head')[0].appendChild(link)
|
||||
}, [enable, icon, icon_background])
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export enum MediaType {
|
||||
mobile = 'mobile',
|
||||
tablet = 'tablet',
|
||||
pc = 'pc',
|
||||
}
|
||||
|
||||
const useBreakpoints = () => {
|
||||
const [width, setWidth] = React.useState(globalThis.innerWidth)
|
||||
const media = (() => {
|
||||
if (width <= 640)
|
||||
return MediaType.mobile
|
||||
if (width <= 768)
|
||||
return MediaType.tablet
|
||||
return MediaType.pc
|
||||
})()
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleWindowResize = () => setWidth(window.innerWidth)
|
||||
window.addEventListener('resize', handleWindowResize)
|
||||
return () => window.removeEventListener('resize', handleWindowResize)
|
||||
}, [])
|
||||
|
||||
return media
|
||||
}
|
||||
|
||||
export default useBreakpoints
|
||||
@@ -0,0 +1,69 @@
|
||||
import { useState } from 'react'
|
||||
import { produce } from 'immer'
|
||||
import { useGetState } from 'ahooks'
|
||||
import type { ConversationItem } from '@/types/app'
|
||||
|
||||
const storageConversationIdKey = 'conversationIdInfo'
|
||||
|
||||
type ConversationInfoType = Omit<ConversationItem, 'inputs' | 'id'>
|
||||
function useConversation() {
|
||||
const [conversationList, setConversationList] = useState<ConversationItem[]>([])
|
||||
const [currConversationId, doSetCurrConversationId, getCurrConversationId] = useGetState<string>('-1')
|
||||
// when set conversation id, we do not have set appId
|
||||
const setCurrConversationId = (id: string, appId: string, isSetToLocalStroge = true, newConversationName = '') => {
|
||||
doSetCurrConversationId(id)
|
||||
if (isSetToLocalStroge && id !== '-1') {
|
||||
// conversationIdInfo: {[appId1]: conversationId1, [appId2]: conversationId2}
|
||||
const conversationIdInfo = globalThis.localStorage?.getItem(storageConversationIdKey) ? JSON.parse(globalThis.localStorage?.getItem(storageConversationIdKey) || '') : {}
|
||||
conversationIdInfo[appId] = id
|
||||
globalThis.localStorage?.setItem(storageConversationIdKey, JSON.stringify(conversationIdInfo))
|
||||
}
|
||||
}
|
||||
|
||||
const getConversationIdFromStorage = (appId: string) => {
|
||||
const conversationIdInfo = globalThis.localStorage?.getItem(storageConversationIdKey) ? JSON.parse(globalThis.localStorage?.getItem(storageConversationIdKey) || '') : {}
|
||||
const id = conversationIdInfo[appId]
|
||||
return id
|
||||
}
|
||||
|
||||
const isNewConversation = currConversationId === '-1'
|
||||
// input can be updated by user
|
||||
const [newConversationInputs, setNewConversationInputs] = useState<Record<string, any> | null>(null)
|
||||
const resetNewConversationInputs = () => {
|
||||
if (!newConversationInputs)
|
||||
return
|
||||
setNewConversationInputs(produce(newConversationInputs, (draft) => {
|
||||
Object.keys(draft).forEach((key) => {
|
||||
draft[key] = ''
|
||||
})
|
||||
}))
|
||||
}
|
||||
const [existConversationInputs, setExistConversationInputs] = useState<Record<string, any> | null>(null)
|
||||
const currInputs = isNewConversation ? newConversationInputs : existConversationInputs
|
||||
const setCurrInputs = isNewConversation ? setNewConversationInputs : setExistConversationInputs
|
||||
|
||||
// info is muted
|
||||
const [newConversationInfo, setNewConversationInfo] = useState<ConversationInfoType | null>(null)
|
||||
const [existConversationInfo, setExistConversationInfo] = useState<ConversationInfoType | null>(null)
|
||||
const currConversationInfo = isNewConversation ? newConversationInfo : existConversationInfo
|
||||
|
||||
return {
|
||||
conversationList,
|
||||
setConversationList,
|
||||
currConversationId,
|
||||
getCurrConversationId,
|
||||
setCurrConversationId,
|
||||
getConversationIdFromStorage,
|
||||
isNewConversation,
|
||||
currInputs,
|
||||
newConversationInputs,
|
||||
existConversationInputs,
|
||||
resetNewConversationInputs,
|
||||
setCurrInputs,
|
||||
currConversationInfo,
|
||||
setNewConversationInfo,
|
||||
setExistConversationInfo,
|
||||
}
|
||||
}
|
||||
|
||||
export default useConversation
|
||||
@@ -0,0 +1,25 @@
|
||||
'use client'
|
||||
import { useCallback } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
||||
const useTimestamp = () => {
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
|
||||
const formatTime = useCallback((value: number, format: string) => {
|
||||
return dayjs.unix(value).tz(timezone).format(format)
|
||||
}, [timezone])
|
||||
|
||||
const formatDate = useCallback((value: string, format: string) => {
|
||||
return dayjs(value).tz(timezone).format(format)
|
||||
}, [timezone])
|
||||
|
||||
return { formatTime, formatDate }
|
||||
}
|
||||
|
||||
export default useTimestamp
|
||||
Reference in New Issue
Block a user