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
9 changes: 9 additions & 0 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@
"Option_popupPlacement_alignOffset_desc": {
"message": "Distance from the aligned position"
},
"Option_popupPlacement_alignOffset_disabled": {
"message": "Disabled when center-aligned"
},
"Option_inheritPopupPlacement": {
"message": "Inherit Menu Display Position from global settings"
},
"Option_inherit": {
"message": "Inherit"
},
"Option_mouse_pointer": {
"message": "Mouse Pointer"
},
Expand Down
9 changes: 9 additions & 0 deletions public/_locales/ja/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@
"Option_popupPlacement_alignOffset_desc": {
"message": "揃えた位置からの距離"
},
"Option_popupPlacement_alignOffset_disabled": {
"message": "中央揃えの場合は無効です"
},
"Option_inheritPopupPlacement": {
"message": "メニュー表示位置を全体設定から継承"
},
"Option_inherit": {
"message": "継承"
},
"Option_mouse_pointer": {
"message": "マウスポインタ"
},
Expand Down
88 changes: 53 additions & 35 deletions src/components/option/editor/PageRuleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useState, useRef } from 'react'
import { useForm, useFieldArray } from 'react-hook-form'
import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
import { Save, BookOpen, ChevronsUpDown, ChevronsDownUp } from 'lucide-react'
import { Save, BookOpen } from 'lucide-react'
import {
Dialog,
DialogClose,
Expand All @@ -17,7 +17,6 @@ import { Form, FormControl, FormField, FormItem } from '@/components/ui/form'
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '@/components/ui/collapsible'
import { Button } from '@/components/ui/button'
import { Tooltip } from '@/components/Tooltip'
Expand All @@ -29,17 +28,20 @@ import { PopupPlacementField } from '@/components/option/field/PopupPlacementFie
import { PopupPlacement } from '@/services/defaultSettings'
import { t as _t } from '@/services/i18n'
const t = (key: string, p?: string[]) => _t(`Option_${key}`, p)
import { POPUP_ENABLED, LINK_COMMAND_ENABLED } from '@/const'
import { POPUP_ENABLED, LINK_COMMAND_ENABLED, INHERIT } from '@/const'
import { e2a, cn } from '@/lib/utils'
import type { PageRule } from '@/types'
import type { PageRule, PopupPlacementOrInherit } from '@/types'
import { PopupPlacementSchema } from '@/types/schema'

import css from './CommandEditDialog.module.css'

export const pageRuleSchema = z.object({
urlPattern: z.string().url({ message: t('zod_url') }),
popupEnabled: z.nativeEnum(POPUP_ENABLED),
popupPlacement: PopupPlacementSchema,
popupPlacement: z.union([
z.literal('inherit'),
PopupPlacementSchema,
]),
linkCommandEnabled: z.nativeEnum(LINK_COMMAND_ENABLED),
})

Expand All @@ -52,7 +54,7 @@ type pageRulesType = z.infer<typeof pageRulesSchema>
const DefaultRule = {
urlPattern: '',
popupEnabled: POPUP_ENABLED.ENABLE,
popupPlacement: PopupPlacement,
popupPlacement: INHERIT as PopupPlacementOrInherit,
linkCommandEnabled: LINK_COMMAND_ENABLED.INHERIT,
}

Expand Down Expand Up @@ -145,8 +147,10 @@ export const PageRuleList = ({
{t('popupEnabled')}: {t(`${field.popupEnabled}`)}
</li>
<li>
{t('popupPlacement')}: {field.popupPlacement.side}{' '}
{field.popupPlacement.align}
{t('popupPlacement')}:{' '}
{field.popupPlacement === INHERIT
? t('inherit')
: `${field.popupPlacement.side} ${field.popupPlacement.align}`}
</li>
<li>
{t('linkCommandEnabled')}:{' '}
Expand Down Expand Up @@ -205,20 +209,29 @@ export const PageRuleDialog = ({
resolver: zodResolver(pageRuleSchema),
mode: 'onChange',
})
const { register, reset, setValue } = form
const { register, reset, setValue, watch } = form
const popupPlacement = watch('popupPlacement')
const [isCollapsibleOpen, setIsCollapsibleOpen] = useState(false)

const handlePopupPlacementSubmit = (
data: z.infer<typeof PopupPlacementSchema>,
) => {
setValue('popupPlacement', data)
}

const handleInheritChange = (inherit: boolean) => {
setValue('popupPlacement', inherit ? INHERIT : PopupPlacement)
setIsCollapsibleOpen(!inherit)
}

useEffect(() => {
if (rule != null && rule.urlPattern !== DefaultRule.urlPattern) {
reset(rule ?? DefaultRule)
reset(rule)
setIsCollapsibleOpen(rule.popupPlacement !== INHERIT)
} else {
setTimeout(() => {
reset(DefaultRule)
setIsCollapsibleOpen(false)
}, 200)
}
}, [rule])
Expand Down Expand Up @@ -267,32 +280,37 @@ export const PageRuleDialog = ({
value: opt,
}))}
/>
<Collapsible
className={cn(css.collapse, 'flex flex-col items-end')}
>
<CollapsibleTrigger className="flex items-center hover:bg-gray-200 p-2 py-1.5 rounded-lg text-sm">
<ChevronsUpDown
size={18}
className={cn(css.icon, css.iconUpDown)}
<div className="space-y-2 pt-2">
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="inheritPopupPlacement"
checked={popupPlacement === INHERIT}
onChange={(e) => handleInheritChange(e.target.checked)}
className="rounded border-gray-300 cursor-pointer"
/>
<ChevronsDownUp
size={18}
className={cn(css.icon, css.iconDownUp)}
/>
<span className="ml-0.5">{t('labelOther')}</span>
</CollapsibleTrigger>
<CollapsibleContent
className={cn(
css.CollapsibleContent,
'w-full space-y-3 pt-2',
)}
<label htmlFor="inheritPopupPlacement" className="text-sm cursor-pointer">
{t('inheritPopupPlacement')}
</label>
</div>
<Collapsible
open={isCollapsibleOpen}
onOpenChange={setIsCollapsibleOpen}
className={cn(css.collapse, 'flex flex-col items-end')}
>
<PopupPlacementField
onSubmit={handlePopupPlacementSubmit}
defaultValues={rule?.popupPlacement ?? PopupPlacement}
/>
</CollapsibleContent>
</Collapsible>
<CollapsibleContent
className={cn(
css.CollapsibleContent,
'w-full space-y-3 pt-2',
)}
>
<PopupPlacementField
onSubmit={handlePopupPlacementSubmit}
defaultValues={typeof popupPlacement === 'string' ? PopupPlacement : popupPlacement}
/>
</CollapsibleContent>
</Collapsible>
</div>
</div>
</Form>
<DialogFooter>
Expand All @@ -305,7 +323,7 @@ export const PageRuleDialog = ({
size="lg"
type="button"
onClick={form.handleSubmit((data) => {
onSubmit(data)
onSubmit(data as PageRule)
onOpenChange(false)
reset(DefaultRule)
})}
Expand Down
25 changes: 20 additions & 5 deletions src/components/option/field/PopupPlacementField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ export const PopupPlacementField = ({
name: 'side',
})

const align = useWatch({
control: form.control,
name: 'align',
})

const isAlignOffsetDisabled = align === ALIGN.center

return (
<section>
<h2 className="text-sm font-bold">{t('popupPlacement')}</h2>
Expand All @@ -70,8 +77,10 @@ export const PopupPlacementField = ({
<ToggleGroup
type="single"
variant="outline"
onValueChange={field.onChange}
defaultValue={field.value}
value={field.value}
onValueChange={(val) => {
if (val) field.onChange(val)
}}
className="grid grid-cols-3 gap-2 p-0.5"
>
<div />
Expand Down Expand Up @@ -127,8 +136,10 @@ export const PopupPlacementField = ({
<ToggleGroup
type="single"
variant="outline"
onValueChange={field.onChange}
defaultValue={field.value}
value={field.value}
onValueChange={(val) => {
if (val) field.onChange(val)
}}
className="grid grid-cols-3 gap-2 p-0.5"
>
<AlignItem
Expand Down Expand Up @@ -157,13 +168,17 @@ export const PopupPlacementField = ({
control={form.control}
name="alignOffset"
formLabel={t('popupPlacement_alignOffset')}
description={t('popupPlacement_alignOffset_desc')}
description={isAlignOffsetDisabled ? t('popupPlacement_alignOffset_disabled') : t('popupPlacement_alignOffset_desc')}
unit="px"
inputProps={{
type: 'number',
min: -100,
max: 100,
step: 5,
disabled: isAlignOffsetDisabled,
className: cn(
isAlignOffsetDisabled && 'opacity-80 cursor-not-allowed'
),
...register('alignOffset', {
valueAsNumber: true,
}),
Expand Down
2 changes: 2 additions & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export enum POPUP_ENABLED {
DISABLE = 'Disable',
}

export const INHERIT = 'inherit'

export enum LINK_COMMAND_ENABLED {
INHERIT = 'Inherit',
ENABLE = 'Enable',
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'
import { Settings } from '../services/settings'
import type { SettingsType, PageRule } from '@/types'
import { isEmpty } from '@/lib/utils'
import { STYLE, STARTUP_METHOD, ALIGN, SIDE } from '@/const'
import { STYLE, STARTUP_METHOD, ALIGN, SIDE, INHERIT } from '@/const'
import Default from '@/services/defaultSettings'

type iconUrlMap = Record<number | string, string>
Expand Down Expand Up @@ -84,7 +84,7 @@ export function useSetting(): useSettingReturn {
return window.location.href.match(re) != null
})

if (pageRule != null) {
if (pageRule != null && pageRule.popupPlacement !== INHERIT) {
settings.popupPlacement = pageRule.popupPlacement
}
}
Expand Down
19 changes: 11 additions & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
EXEC_STATE,
} from '@/const'
import type { PageAction } from '@/services/pageAction'
import { INHERIT } from '@/const'

export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]
Expand Down Expand Up @@ -100,10 +101,19 @@ export type CommandVariable = {
value: string
}

export type PopupPlacement = {
side: SIDE
align: ALIGN
sideOffset: number
alignOffset: number
}

export type PopupPlacementOrInherit = PopupPlacement | typeof INHERIT

export type PageRule = {
urlPattern: string
popupEnabled: POPUP_ENABLED
popupPlacement: PopupPlacement
popupPlacement: PopupPlacementOrInherit
linkCommandEnabled: LINK_COMMAND_ENABLED
}

Expand All @@ -118,13 +128,6 @@ export type StartupMethod = {
leftClickHoldParam?: number
}

export type PopupPlacement = {
side: SIDE
align: ALIGN
sideOffset: number
alignOffset: number
}

export type Star = {
id: string
}
Expand Down
26 changes: 13 additions & 13 deletions src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ import {
import { t } from '@/services/i18n'

export const PopupPlacementSchema = z.object({
side: z.nativeEnum(SIDE),
align: z.nativeEnum(ALIGN),
sideOffset: z
.number({ message: t('Option_zod_number') })
.min(0, { message: t('Option_zod_number_min', ['0']) })
.max(100, { message: t('Option_zod_number_max', ['100']) })
.default(0),
alignOffset: z
.number({ message: t('Option_zod_number') })
.min(-100, { message: t('Option_zod_number_min', ['-100']) })
.max(100, { message: t('Option_zod_number_max', ['100']) })
.default(0),
})
side: z.nativeEnum(SIDE),
align: z.nativeEnum(ALIGN),
sideOffset: z
.number({ message: t('Option_zod_number') })
.min(0, { message: t('Option_zod_number_min', ['0']) })
.max(100, { message: t('Option_zod_number_max', ['100']) })
.default(0),
alignOffset: z
.number({ message: t('Option_zod_number') })
.min(-100, { message: t('Option_zod_number_min', ['-100']) })
.max(100, { message: t('Option_zod_number_max', ['100']) })
.default(0),
})

const PageActionStartSchema = z.object({
type: z.literal(PAGE_ACTION_CONTROL.start),
Expand Down