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
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@
"@crowdin/crowdin-api-client": "^1.49.0",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/css": "^11.13.5",
"@rsdoctor/rspack-plugin": "^1.3.11",
"@rspack/cli": "^1.6.4",
"@rspack/core": "^1.6.4",
"@rsdoctor/rspack-plugin": "^1.3.12",
"@rspack/cli": "^1.6.6",
"@rspack/core": "^1.6.6",
"@swc/core": "^1.15.3",
"@swc/jest": "^0.2.39",
"@types/chrome": "0.1.31",
"@types/chrome": "0.1.32",
"@types/decompress": "^4.2.7",
"@types/jest": "^30.0.0",
"@types/node": "^24.10.1",
"@types/punycode": "^2.1.4",
"@vue/babel-plugin-jsx": "^2.0.1",
"babel-loader": "^10.0.0",
"commitlint": "^20.1.0",
"commitlint": "^20.2.0",
"css-loader": "^7.1.2",
"decompress": "^4.2.1",
"husky": "^9.1.7",
Expand All @@ -54,7 +54,7 @@
"postcss": "^8.5.6",
"postcss-loader": "^8.2.0",
"postcss-rtlcss": "^5.7.1",
"puppeteer": "^24.31.0",
"puppeteer": "^24.32.0",
"ts-loader": "^9.5.4",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
Expand All @@ -63,9 +63,9 @@
"dependencies": {
"@element-plus/icons-vue": "^2.3.2",
"echarts": "^6.0.0",
"element-plus": "2.11.8",
"element-plus": "2.12.0",
"punycode": "^2.3.1",
"vue": "^3.5.24",
"vue": "^3.5.25",
"vue-router": "^4.6.3"
},
"engines": {
Expand Down
5 changes: 4 additions & 1 deletion src/api/chrome/tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

import { handleError } from "./common"

export function getTab(id: number): Promise<ChromeTab> {
export function getTab(id: number): Promise<ChromeTab | undefined> {
if (id < 0) {
return Promise.resolve(undefined)
}
return new Promise(resolve => chrome.tabs.get(id, tab => {
handleError("getTab")
resolve(tab)
Expand Down
1 change: 1 addition & 0 deletions src/background/track-server/file-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Context = {

async function convertContext(tabId: number): Promise<Context | null> {
const tab = await getTab(tabId)
if (!tab) return null
const { active, url } = tab
if (!active || !url) return null
const fileHost = extractFileHost(url)
Expand Down
2 changes: 1 addition & 1 deletion src/background/whitelist-menu-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const menuInitialOptions: ChromeContextMenuCreateProps = {
async function updateContextMenuInner(param: ChromeTab | number | undefined): Promise<void> {
if (typeof param === 'number') {
// If number, get the tabInfo first
const tab: ChromeTab = await getTab(currentActiveId)
const tab = await getTab(currentActiveId)
tab && await updateContextMenuInner(tab)
} else {
const { url } = param || {}
Expand Down
41 changes: 41 additions & 0 deletions src/pages/side/components/Search/Cell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { formatTimeYMD } from '@util/time'
import { type DateCell, useNamespace } from "element-plus"
import { computed, defineComponent } from 'vue'

const DOT_SIZE = '3px'
const DATE_SIZE = '22px'

const Cell = defineComponent<{ cell: DateCell, dataDates: string[] }>(props => {
const text = computed(() => {
const { renderText, text } = props.cell
return renderText ?? text
})
const hasData = computed(() => {
const { date } = props.cell
if (!date) return false
const dateStr = formatTimeYMD(date)
return props.dataDates.includes(dateStr)
})
const ns = useNamespace('date-table-cell')

return () => (
<div class={ns.b()}>
<span
class={ns.e('text')}
style={{ width: DATE_SIZE, height: DATE_SIZE, lineHeight: DATE_SIZE }}
>{text.value}</span>
{hasData.value && <span style={{
position: 'absolute',
width: DOT_SIZE,
height: DOT_SIZE,
background: 'var(--el-color-primary)',
borderRadius: '50%',
bottom: '1px',
left: '50%',
transform: 'translateX(-50%)',
}} />}
</div>
)
}, { props: ['cell', 'dataDates'] })

export default Cell
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { Search } from "@element-plus/icons-vue"
import { css } from '@emotion/css'
import { useState } from "@hooks"
import Flex from "@pages/components/Flex"
import { getDatePickerIconSlots } from "@pages/element-ui/rtl"
import { getDatePickerIconSlots } from '@pages/element-ui/rtl'
import { t } from "@side/locale"
import { ElDatePicker, ElInput, useNamespace } from "element-plus"
import { defineComponent, watch } from "vue"
import { type DateCell, ElDatePicker, ElInput, useNamespace } from "element-plus"
import { defineComponent, h } from "vue"
import Cell from './Cell'
import { useDatePicker } from './useDatePicker'

const useCalendarStyle = () => {
const inputNs = useNamespace('input')
Expand Down Expand Up @@ -48,13 +50,12 @@ type Props = {
}

const _default = defineComponent<Props>(props => {
const now = Date.now()

const [query, setQuery] = useState(props.defaultQuery)
const [date, setDate] = useState(props.defaultDate)
const handleSearch = () => props.onSearch?.(query.value.trim(), date.value)

watch(date, handleSearch)
const {
date, setDate, dataDates,
disabledDate, onPanelChange,
} = useDatePicker({ onChange: handleSearch })

const [calendarCls, popoverCls] = useCalendarStyle()

Expand All @@ -72,15 +73,19 @@ const _default = defineComponent<Props>(props => {
}}
onKeydown={kv => (kv as KeyboardEvent).code === 'Enter' && handleSearch()}
/>
<ElDatePicker
clearable={false}
disabledDate={(date: Date) => date.getTime() > now}
modelValue={date.value}
onUpdate:modelValue={setDate}
class={calendarCls}
popperClass={popoverCls}
v-slots={getDatePickerIconSlots()}
/>
{/* The events of date picker is not compatible with typescript, so use h() to workaround */}
{h(ElDatePicker, {
clearable: false,
disabledDate,
modelValue: date.value,
'onUpdate:modelValue': setDate,
class: calendarCls,
popperClass: popoverCls,
onPanelChange,
}, {
...getDatePickerIconSlots(),
default: (cell: DateCell) => <Cell cell={cell} dataDates={dataDates.value} />,
})}
</Flex>
)
}, { props: ['defaultDate', 'defaultQuery', 'onSearch'] })
Expand Down
38 changes: 38 additions & 0 deletions src/pages/side/components/Search/useDatePicker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useRequest } from '@hooks/useRequest'
import { useState } from '@hooks/useState'
import { selectSite } from '@service/stat-service'
import { getMonthTime, MILL_PER_WEEK } from '@util/time'
import { watch } from 'vue'

export const useDatePicker = (options: { onChange: ArgCallback<Date> }) => {
const { onChange } = options
const [date, setDate] = useState(new Date())

watch(date, val => onChange(val))

const { data: dataDates, refresh: refreshDates } = useRequest(async (dateInMonth: Date) => {
const [ms, me] = getMonthTime(dateInMonth)
const start = new Date(ms.getTime() - ms.getDay() * MILL_PER_WEEK)
const end = new Date(me.getTime() + (6 - me.getDay()) * MILL_PER_WEEK)

const stats = await selectSite({ date: [start, end] })
const dateSet = new Set<string>()
stats.forEach(({ date }) => date && dateSet.add(date))
return Array.from(dateSet)
}, { defaultValue: [], defaultParam: [new Date()] })

const onPanelChange = (val: Date | Date[], mode: 'year' | 'month') => {
if (mode !== 'month') return
const date = Array.isArray(val) ? val[0] : val
if (!date) return
refreshDates(date)
}

const disabledDate = (date: Date) => date.getTime() > Date.now()

return {
dataDates, date, setDate,
onPanelChange,
disabledDate,
}
}