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
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@
},
"license": "MIT",
"devDependencies": {
"@crowdin/crowdin-api-client": "^1.51.1",
"@crowdin/crowdin-api-client": "^1.52.0",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/css": "^11.13.5",
"@rsdoctor/rspack-plugin": "^1.5.0",
"@rspack/cli": "^1.7.2",
"@rspack/core": "^1.7.2",
"@swc/core": "^1.15.8",
"@rspack/cli": "^1.7.3",
"@rspack/core": "^1.7.3",
"@swc/core": "^1.15.10",
"@swc/jest": "^0.2.39",
"@types/chrome": "0.1.33",
"@types/chrome": "0.1.35",
"@types/decompress": "^4.2.7",
"@types/jest": "^30.0.0",
"@types/node": "^25.0.8",
"@types/node": "^25.0.9",
"@types/punycode": "^2.1.4",
"@vue/babel-plugin-jsx": "^2.0.1",
"babel-loader": "^10.0.0",
Expand All @@ -65,7 +65,7 @@
"echarts": "^6.0.0",
"element-plus": "2.13.1",
"punycode": "^2.3.1",
"vue": "^3.5.26",
"vue": "^3.5.27",
"vue-router": "^4.6.4"
},
"engines": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ const TitleSelect = defineComponent<Props>(({ values, field }) => {
onChange={val => filter[field] = val as number}
popperOptions={{ placement: 'bottom' }}
popperClass={popoverCls}
>
{values.map(k => <ElSelect.Option key={k} label={k} value={k} />)}
</ElSelect >
options={values.map(k => ({ label: k, value: k }))}
/>
)
}, { props: ['field', "values"] })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
* https://opensource.org/licenses/MIT
*/
import { t } from "@app/locale"
import { ElOption, ElSelect, ElTimePicker } from "element-plus"
import { ElSelect, ElTimePicker } from "element-plus"
import { computed, defineComponent, StyleValue } from "vue"

const ALL_MODES: timer.option.DarkMode[] = ["default", "on", "off", "timed"]
const labelOfMode = (mode: timer.option.DarkMode) => mode === 'default'
? t(msg => msg.option.followBrowser)
: t(msg => msg.option.appearance.darkMode.options[mode])

function computeSecondToDate(secondOfDate: number): Date {
const now = new Date()
Expand Down Expand Up @@ -46,14 +49,8 @@ const _default = defineComponent<Props>(props => {
size="small"
style={{ width: "120px" }}
onChange={val => props.onChange?.(val as timer.option.DarkMode, [props.startSecond, props.endSecond])}
>
{
ALL_MODES.map(value => <ElOption
value={value}
label={t(msg => value === 'default' ? msg.option.followBrowser : msg.option.appearance.darkMode.options[value])}
/>)
}
</ElSelect>
options={ALL_MODES.map(value => ({ value, label: labelOfMode(value) }))}
/>
{props.modelValue === "timed" && <>
<ElTimePicker
modelValue={start.value}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import optionService from "@service/option-service"
import { IS_ANDROID } from "@util/constant/environment"
import { defaultAppearance } from "@util/constant/option"
import { toggle } from "@util/dark-mode"
import { ElColorPicker, ElMessageBox, ElOption, ElSelect, ElSlider, ElSwitch, ElTag, type TagProps } from "element-plus"
import { ElColorPicker, ElMessageBox, ElSelect, ElSlider, ElSwitch, ElTag, type TagProps } from "element-plus"
import { computed, defineComponent, type StyleValue } from "vue"
import { type OptionInstance } from "../../common"
import { useOption } from "../../useOption"
Expand All @@ -23,10 +23,16 @@ import OptionLines from '../OptionLines'
import OptionTag from '../OptionTag'
import DarkModeInput from "./DarkModeInput"

const FOLLOW_BROWSER: I18nKey = msg => msg.option.followBrowser

const SORTED_LOCALES: timer.Locale[] = ALL_LOCALES
// Keep the locale same as this browser first position
.sort((a, _b) => a === localeSameAsBrowser ? -1 : 0)
const allLocaleOptions: timer.option.LocaleOption[] = ["default", ...SORTED_LOCALES]

const allLocaleOptions = (["default", ...SORTED_LOCALES] satisfies timer.option.LocaleOption[]).map(locale => ({
value: locale,
label: locale === "default" ? t(FOLLOW_BROWSER) : localeMessages[locale].name
}))

function copy(target: timer.option.AppearanceOption, source: timer.option.AppearanceOption) {
target.displayWhitelistMenu = source.displayWhitelistMenu
Expand All @@ -42,7 +48,7 @@ function copy(target: timer.option.AppearanceOption, source: timer.option.Appear

const DEFAULT_ANIMA_DURATION = defaultAppearance().chartAnimationDuration
const DEFAULT_SIDE_PANEL_ENABLED = true
const FOLLOW_BROWSER: I18nKey = msg => msg.option.followBrowser


const _default = defineComponent((_props, ctx) => {
const { option } = useOption<timer.option.AppearanceOption>({
Expand Down Expand Up @@ -107,12 +113,8 @@ const _default = defineComponent((_props, ctx) => {
style={{ width: "120px" }}
onChange={(newVal: timer.option.LocaleOption) => handleLocaleChange(newVal)}
filterable
>
{allLocaleOptions.map(locale => <ElOption
value={locale}
label={locale === "default" ? t(FOLLOW_BROWSER) : localeMessages[locale].name}
/>)}
</ElSelect>
options={allLocaleOptions}
/>
</OptionItem>
{!IS_ANDROID && <>
<OptionItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
DEFAULT_ENDPOINT as DEFAULT_OBSIDIAN_ENDPOINT,
} from "@api/obsidian"
import { t } from "@app/locale"
import { ElInput, ElOption, ElSelect } from "element-plus"
import { ElInput, ElSelect } from "element-plus"
import { computed, defineComponent } from "vue"
import { type OptionInstance } from "../../common"
import OptionItem from "../OptionItem"
Expand Down Expand Up @@ -53,9 +53,8 @@ const _default = defineComponent((_, ctx) => {
modelValue={backupType.value}
size="small"
onChange={(val: timer.backup.Type) => backupType.value = val}
>
{ALL_TYPES.map(type => <ElOption value={type} label={TYPE_NAMES[type]} />)}
</ElSelect>
options={ALL_TYPES.map(value => ({ value, label: TYPE_NAMES[value] }))}
/>
</OptionItem >
<OptionItem
v-show={isNotNone.value}
Expand Down
12 changes: 5 additions & 7 deletions src/pages/app/components/Option/components/LimitOption/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Edit } from "@element-plus/icons-vue"
import { css } from '@emotion/css'
import { locale } from '@i18n'
import { defaultLimit } from "@util/constant/option"
import { ElButton, ElInput, ElInputNumber, ElMessage, ElMessageBox, ElOption, ElSelect, ElSwitch, useNamespace } from "element-plus"
import { ElButton, ElInput, ElInputNumber, ElMessage, ElMessageBox, ElSelect, ElSwitch, useNamespace } from "element-plus"
import { defineComponent, type StyleValue } from "vue"
import { type OptionInstance } from "../../common"
import { useOption } from "../../useOption"
Expand Down Expand Up @@ -150,9 +150,8 @@ const _default = defineComponent((_, ctx) => {
class={levelSelectStyle.cls}
style={{ width: `${levelSelectStyle.width}px` }}
onChange={handleLevelChange}
>
{ALL_LEVEL.map(item => <ElOption value={item} label={t(msg => msg.option.limit.level[item])} />)}
</ElSelect>
options={ALL_LEVEL.map(value => ({ value, label: t(msg => msg.option.limit.level[value]) }))}
/>
</OptionItem>
<OptionItem
v-show={option.limitLevel === "password"}
Expand Down Expand Up @@ -181,9 +180,8 @@ const _default = defineComponent((_, ctx) => {
.then(() => option.limitVerifyDifficulty = val)
.catch(console.warn)
}
>
{ALL_DIFF.map(item => <ElOption value={item} label={t(msg => msg.option.limit.level.verificationDifficulty[item])} />)}
</ElSelect>
options={ALL_DIFF.map(value => ({ value, label: t(msg => msg.option.limit.level.verificationDifficulty[value]) }))}
/>
<ElButton
size="small"
style={{ height: '28px', marginInlineStart: '5px' } satisfies StyleValue}
Expand Down
7 changes: 3 additions & 4 deletions src/pages/app/components/Option/components/TrackingOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { rotate } from "@util/array"
import { IS_ANDROID, IS_FIREFOX } from "@util/constant/environment"
import { defaultTracking } from "@util/constant/option"
import { MILL_PER_SECOND } from "@util/time"
import { ElMessage, ElMessageBox, ElOption, ElSelect, ElSwitch, ElTimePicker, ElTooltip } from "element-plus"
import { ElMessage, ElMessageBox, ElSelect, ElSwitch, ElTimePicker, ElTooltip } from "element-plus"
import { computed, defineComponent } from "vue"
import { type OptionInstance } from "../common"
import { useOption } from "../useOption"
Expand Down Expand Up @@ -149,9 +149,8 @@ const _default = defineComponent((_props, ctx) => {
size="small"
style={{ width: '120px' }}
onChange={(val: timer.option.WeekStartOption) => option.weekStart = val}
>
{weekStartOptionPairs.map(([val, label]) => <ElOption value={val} label={label} />)}
</ElSelect>
options={weekStartOptionPairs.map(([value, label]) => ({ value, label }))}
/>
</OptionItem>
</OptionLines>
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ const CategorySelect = defineComponent<Props>((props, ctx) => {
)
}, { props: ['clearable', 'modelValue', 'size', 'width', 'onVisibleChange', 'onChange'] })

export default CategorySelect
export default CategorySelect
13 changes: 6 additions & 7 deletions src/pages/app/components/common/filter/CategoryFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCategory } from "@app/context"
import { t } from "@app/locale"
import { CATE_NOT_SET_ID } from "@util/site"
import { ElOption, ElSelect } from "element-plus"
import { ElSelect } from "element-plus"
import { computed, defineComponent, type StyleValue } from "vue"

type Props = ModelValue<number[] | undefined> & {
Expand All @@ -12,9 +12,9 @@ type Props = ModelValue<number[] | undefined> & {
const CategoryFilter = defineComponent<Props>(props => {
const cate = useCategory()

const displayCategories = computed(() => [
{ id: CATE_NOT_SET_ID, name: t(msg => msg.shared.cate.notSet) } satisfies timer.site.Cate,
...cate.all,
const options = computed(() => [
{ value: CATE_NOT_SET_ID, label: t(msg => msg.shared.cate.notSet) },
...cate.all.map(c => ({ value: c.id, label: c.name }))
])

return () => cate.enabled ? (
Expand All @@ -29,9 +29,8 @@ const CategoryFilter = defineComponent<Props>(props => {
onClear={() => props.onChange?.(undefined)}
placeholder={t(msg => msg.siteManage.column.cate)}
style={{ width: '200px' } satisfies StyleValue}
>
{displayCategories.value?.map(cate => <ElOption value={cate.id} label={cate.name} />)}
</ElSelect>
options={options.value}
/>
) : null
}, { props: ['modelValue', 'onChange', 'disabled', 'useCache'] })

Expand Down
72 changes: 35 additions & 37 deletions src/pages/app/components/common/filter/MultiSelectFilterItem.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
import { useCached } from "@hooks"
import { ElOption, ElSelect } from "element-plus"
import { defineComponent, type PropType, watch } from "vue"
import { ElSelect } from "element-plus"
import { defineComponent, watch } from "vue"
import { useRoute } from "vue-router"
import { SELECT_WRAPPER_STYLE } from "./common"

const MultiSelectFilterItem = defineComponent({
props: {
defaultValue: Array as PropType<(string | number)[]>,
/**
* Whether to save the value in the localStorage with {@param historyName}
*/
historyName: String,
placeholder: String,
disabled: Boolean,
options: Array as PropType<{ value: string | number, label?: string }[]>,
},
emits: {
change: (_val: (string | number)[]) => true,
},
setup(props, ctx) {
const cacheKey = props.historyName && `__filter_item_multi_select_${useRoute().path}_${props.historyName}`
const { data, setter } = useCached(cacheKey, props.defaultValue)
watch(data, () => ctx.emit('change', data.value ?? []))
type Data = string | number

return () => (
<ElSelect
modelValue={data.value}
onChange={setter}
multiple
clearable
collapseTags
disabled={props.disabled}
onClear={() => setter([])}
placeholder={props.placeholder}
style={SELECT_WRAPPER_STYLE}
>
{props.options?.map(({ value, label }) => <ElOption value={value} label={label ?? value} />)}
</ElSelect>
)
}
})
type Props = {
defaultValue?: Data[]
/**
* Whether to save the value in the localStorage with {@param historyName}
*/
historyName?: string
placeholder?: string
disabled?: boolean
options?: { value: Data, label?: string }[]
onChange?: (val: Data[]) => void
}

const MultiSelectFilterItem = defineComponent<Props>(props => {
const cacheKey = props.historyName && `__filter_item_multi_select_${useRoute().path}_${props.historyName}`
const { data, setter } = useCached<Data[]>(cacheKey, props.defaultValue)
watch(data, val => props.onChange?.(val ?? []))

return () => (
<ElSelect
modelValue={data.value}
onChange={setter}
multiple
clearable
collapseTags
disabled={props.disabled}
onClear={() => setter([])}
placeholder={props.placeholder}
style={SELECT_WRAPPER_STYLE}
options={props.options}
/>
)
}, { props: ['defaultValue', 'historyName', 'placeholder', 'disabled', 'options'] })

export default MultiSelectFilterItem
56 changes: 26 additions & 30 deletions src/pages/app/components/common/filter/SelectFilterItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,33 @@
*/

import { useCached } from "@hooks"
import { ElOption, ElSelect } from "element-plus"
import { defineComponent, watch, type PropType } from "vue"
import { ElSelect } from "element-plus"
import { defineComponent, watch } from "vue"
import { useRoute } from "vue-router"
import { SELECT_WRAPPER_STYLE } from "./common"

const _default = defineComponent({
props: {
defaultValue: String,
/**
* Whether to save the value in the localStorage with {@param historyName}
*/
historyName: String,
options: Object as PropType<Record<string | number, string>>
},
emits: {
select: (_val: string | undefined) => true
},
setup(props, ctx) {
const cacheKey = props.historyName && `__filter_item_select_${useRoute().path}_${props.historyName}`
const { data, setter } = useCached(cacheKey, props.defaultValue)
watch(data, () => ctx.emit('select', data.value))
return () => (
<ElSelect
modelValue={data.value}
onChange={setter}
style={SELECT_WRAPPER_STYLE}
>
{Object.entries(props.options || {}).map(([value, label]) => <ElOption label={label} value={value} />)}
</ElSelect>
)
}
})
type Props = {
defaultValue?: string
/**
* Whether to save the value in the localStorage with {@param historyName}
*/
historyName?: string
options: Record<string, string>
onSelect?: (val: string | undefined) => void
}

export default _default
const SelectFilterItem = defineComponent<Props>(props => {
const cacheKey = props.historyName && `__filter_item_select_${useRoute().path}_${props.historyName}`
const { data, setter } = useCached(cacheKey, props.defaultValue)
watch(data, val => props.onSelect?.(val))
return () => (
<ElSelect
modelValue={data.value}
onChange={setter}
style={SELECT_WRAPPER_STYLE}
options={Object.entries(props.options).map(([value, label]) => ({ label, value }))}
/>
)
}, { props: ['defaultValue', 'historyName', 'options', 'onSelect'] })

export default SelectFilterItem
Loading