Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/database/memory-detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import StoragePromise from "./common/storage-promise"
/**
* User memory of this extension
*/
type MemoryInfo = {
export type MemoryInfo = {
/**
* Used bytes
*/
Expand Down
30 changes: 12 additions & 18 deletions src/pages/app/components/About/DescLink.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { ElLink } from "element-plus"
import { defineComponent, h, useSlots, type PropType } from "vue"
import { defineComponent, h, useSlots } from "vue"
import "./desc-link.sass"

export type Icon = "github" | "element-plus" | "echarts" | "vue"
type Icon = "github" | "element-plus" | "echarts" | "vue"

const _default = defineComponent({
props: {
href: String,
icon: String as PropType<Icon>
},
setup(props) {
const { icon, href } = props
const { default: default_ } = useSlots()
return () => (
<ElLink href={href} target="_blank">
{icon ? <div class={`i-about-icon i-about-icons-${icon}`} /> : null}
{!!default_ && h(default_)}
</ElLink>
)
}
})
const _default = defineComponent<{ href?: string, icon?: Icon }>(props => {
const { icon, href } = props
const { default: default_ } = useSlots()
return () => (
<ElLink href={href} target="_blank">
{icon ? <div class={`i-about-icon i-about-icons-${icon}`} /> : null}
{!!default_ && h(default_)}
</ElLink>
)
}, { props: ['href', 'icon'] })

export default _default
27 changes: 10 additions & 17 deletions src/pages/app/components/About/InstallationLink.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { type PropType, defineComponent } from "vue"
import { defineComponent } from "vue"
import "./installation-link.sass"

type _Source = 'chrome' | 'firefox' | 'edge' | 'kiwi'

const _default = defineComponent({
props: {
source: String as PropType<_Source>,
name: String,
href: String,
},
setup({ source, name, href }) {
return () =>
<div class="installation-link-container">
<a href={href} target="_blank" class="installation-link">
<div class={`i-logos i-logos-${source}`} />
<span class="installation-name">{name}</span>
</a>
</div>
}
})
const _default = defineComponent<{ source: _Source, name: string, href: string }>(({ source, name, href }) => {
return () =>
<div class="installation-link-container">
<a href={href} target="_blank" class="installation-link">
<div class={`i-logos i-logos-${source}`} />
<span class="installation-name">{name}</span>
</a>
</div>
}, { props: ['source', 'name', 'href'] })

export default _default
3 changes: 0 additions & 3 deletions src/pages/app/components/Analysis/common.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import siteService from "@service/site-service"
import statService from "@service/stat-service"
import { identifySiteKey, parseSiteKeyFromIdentity, SiteMap } from "@util/site"
import { useDebounce } from "@vueuse/core"
import { ElSelectV2, ElTag } from "element-plus"
import { ElSelectV2, ElTag, useNamespace } from "element-plus"
import type { OptionType } from "element-plus/es/components/select-v2/src/select.types"
import { computed, defineComponent, type PropType, type StyleValue } from "vue"
import { computed, defineComponent, onMounted, ref, type PropType, type StyleValue } from "vue"
import { useAnalysisTarget } from "../../context"
import type { AnalysisTarget } from "../../types"
import { labelOfHostInfo } from "../../util"

Expand Down Expand Up @@ -113,77 +114,82 @@ const SiteOption = defineComponent({
},
})

const TargetSelect = defineComponent({
props: {
modelValue: Object as PropType<AnalysisTarget>,
},
emits: {
change: (_val?: AnalysisTarget) => true,
},
setup(props, ctx) {
const { categories } = useCategories()
const selectKey = computed(() => cvtTarget2Key(props.modelValue))

const emitChange = (selectKey?: string) => {
const target = cvtKey2Target(selectKey)
ctx.emit('change', target)
}
const TargetSelect = defineComponent(() => {
const { categories } = useCategories()

const { data: allItems } = useRequest(
() => fetchItems(categories.value),
{ deps: categories },
)
const target = useAnalysisTarget()
const selectKey = computed({
get: () => cvtTarget2Key(target.value),
set: key => target.value = cvtKey2Target(key),
})

const [query, setQuery] = useState('')
const debouncedQuery = useDebounce<string>(query, 50)

const options = computed(() => {
const q = debouncedQuery.value?.trim?.()
let [cateItems, siteItems] = allItems.value || []
if (q) {
siteItems = siteItems?.filter(item => {
const { host, alias } = (item.key as timer.site.SiteInfo) || {}
return host?.includes?.(q) || alias?.includes?.(q)
})
cateItems = cateItems?.filter(item => item.label?.includes?.(q))
}

let res: OptionType[] = []
cateItems?.length && res.push({
value: 'cate',
label: t(msg => msg.analysis.target.cate),
options: cateItems.map(item => ({ value: cvtTarget2Key(item), label: item.label, data: item })),
const { data: allItems } = useRequest(
() => fetchItems(categories.value),
{ deps: categories },
)

const [query, setQuery] = useState('')
const debouncedQuery = useDebounce<string>(query, 50)

const options = computed(() => {
const q = debouncedQuery.value?.trim?.()
let [cateItems, siteItems] = allItems.value || []
if (q) {
siteItems = siteItems?.filter(item => {
const { host, alias } = (item.key as timer.site.SiteInfo) || {}
return host?.includes?.(q) || alias?.includes?.(q)
})
siteItems?.length && res.push({
value: 'site',
label: t(msg => msg.analysis.target.site),
options: siteItems.map(item => ({ value: cvtTarget2Key(item), label: item.label, data: item })),
})
if (res.length === 1) {
// Single content, not use group
res = res[0].options
}
return res
cateItems = cateItems?.filter(item => item.label?.includes?.(q))
}

let res: OptionType[] = []
cateItems?.length && res.push({
value: 'cate',
label: t(msg => msg.analysis.target.cate),
options: cateItems.map(item => ({ value: cvtTarget2Key(item), label: item.label, data: item })),
})
siteItems?.length && res.push({
value: 'site',
label: t(msg => msg.analysis.target.site),
options: siteItems.map(item => ({ value: cvtTarget2Key(item), label: item.label, data: item })),
})
if (res.length === 1) {
// Single content, not use group
res = res[0].options
}
return res
})

return () => (
<ElSelectV2
placeholder={t(msg => msg.analysis.common.hostPlaceholder)}
modelValue={selectKey.value}
filterable
filterMethod={setQuery}
onChange={emitChange}
style={{ width: '240px' } as StyleValue}
defaultFirstOption
options={options.value ?? []}
fitInputWidth={false}
v-slots={({ item }: any) => {
const target = (item as any).data as TargetItem
return target?.type === 'site' ? <SiteOption value={target?.key} /> : target?.label
}}
/>
)
},
const ns = useNamespace('select')
const select = ref<InstanceType<typeof ElSelectV2>>()
onMounted(() => {
if (target.value) return
let el = select.value?.$el as HTMLElement | undefined
if (!el) return
el.click()
const input = el.querySelector(`.${ns.e('input')}`) as HTMLInputElement
(el.querySelector(`.${ns.e('wrapper')}`) as HTMLElement)?.classList?.add?.(ns.is('focused'))
input?.click?.()
})

return () => (
<ElSelectV2
ref={select}
placeholder={t(msg => msg.analysis.common.hostPlaceholder)}
modelValue={selectKey.value}
onChange={val => selectKey.value = val}
filterable
filterMethod={setQuery}
style={{ width: '240px' } as StyleValue}
defaultFirstOption
options={options.value ?? []}
fitInputWidth={false}
v-slots={({ item }: any) => {
const target = (item as any).data as TargetItem
return target?.type === 'site' ? <SiteOption value={target?.key} /> : target?.label
}}
/>
)
})

export default TargetSelect
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,23 @@
*/

import TimeFormatFilterItem from "@app/components/common/filter/TimeFormatFilterItem"
import { useState } from "@hooks"
import Flex from "@pages/components/Flex"
import { defineComponent, type PropType, ref, VNode, VNodeRef, watch } from "vue"
import type { AnalysisTarget } from "../../types"
import { defineComponent } from "vue"
import { useAnalysisTimeFormat } from "../../context"
import TargetSelect from "./TargetSelect"
import { useNamespace } from "element-plus"

export type AnalysisFilterInstance = {
openTargetSelect: () => void
}
const AnalysisFilter = defineComponent(() => {
const timeFormat = useAnalysisTimeFormat()

const AnalysisFilter = defineComponent({
props: {
target: Object as PropType<AnalysisTarget>,
timeFormat: {
type: String as PropType<timer.app.TimeFormat>,
required: true,
}
},
emits: {
targetChange: (_target: AnalysisTarget | undefined) => true,
timeFormatChange: (_format: timer.app.TimeFormat) => true,
},
setup(props, ctx) {
const [target, setTarget] = useState(props.target)
const [timeFormat, setTimeFormat] = useState(props.timeFormat)
watch(target, () => ctx.emit('targetChange', target.value))
watch(timeFormat, () => ctx.emit('timeFormatChange', timeFormat.value))

const targetSelect: VNodeRef = ref()
const { is } = useNamespace('select')
const openTargetSelect = () => {
const targetEl = targetSelect.value?.$el as HTMLDivElement
targetEl?.click?.()
const input = targetEl?.querySelector('.el-select__input') as HTMLInputElement
(targetEl?.querySelector('.el-select__wrapper') as HTMLElement)?.classList?.add?.(is('focused'))
// input?.focus?.()
input?.click?.()
}

ctx.expose({ openTargetSelect } satisfies AnalysisFilterInstance)

return () => (
<Flex gap={10}>
<TargetSelect
ref={targetSelect}
modelValue={target.value}
onChange={setTarget}
/>
<TimeFormatFilterItem
defaultValue={timeFormat.value}
onChange={setTimeFormat}
/>
</Flex>
)
}
return () => (
<Flex gap={10}>
<TargetSelect />
<TimeFormatFilterItem
modelValue={timeFormat.value}
onChange={val => timeFormat.value = val}
/>
</Flex>
)
})

export default AnalysisFilter
Loading
Loading