From e80bafee1225c2f391f78e928d484486abecafd9 Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Thu, 15 May 2025 23:41:45 +0900 Subject: [PATCH 1/3] Update: Prevent from being unselected. --- src/components/option/field/PopupPlacementField.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/option/field/PopupPlacementField.tsx b/src/components/option/field/PopupPlacementField.tsx index f78c2964..543f441e 100644 --- a/src/components/option/field/PopupPlacementField.tsx +++ b/src/components/option/field/PopupPlacementField.tsx @@ -70,8 +70,10 @@ export const PopupPlacementField = ({ { + if (val) field.onChange(val) + }} className="grid grid-cols-3 gap-2 p-0.5" >
@@ -127,8 +129,10 @@ export const PopupPlacementField = ({ { + if (val) field.onChange(val) + }} className="grid grid-cols-3 gap-2 p-0.5" > Date: Thu, 15 May 2025 23:50:15 +0900 Subject: [PATCH 2/3] Update: Disable offset specification when centering. --- public/_locales/en/messages.json | 3 +++ public/_locales/ja/messages.json | 3 +++ src/components/option/field/PopupPlacementField.tsx | 13 ++++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index b871e4d3..1853063f 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -194,6 +194,9 @@ "Option_popupPlacement_alignOffset_desc": { "message": "Distance from the aligned position" }, + "Option_popupPlacement_alignOffset_disabled": { + "message": "Disabled when center-aligned" + }, "Option_mouse_pointer": { "message": "Mouse Pointer" }, diff --git a/public/_locales/ja/messages.json b/public/_locales/ja/messages.json index 3dc35d93..aab3409e 100644 --- a/public/_locales/ja/messages.json +++ b/public/_locales/ja/messages.json @@ -194,6 +194,9 @@ "Option_popupPlacement_alignOffset_desc": { "message": "揃えた位置からの距離" }, + "Option_popupPlacement_alignOffset_disabled": { + "message": "中央揃えの場合は無効です" + }, "Option_mouse_pointer": { "message": "マウスポインタ" }, diff --git a/src/components/option/field/PopupPlacementField.tsx b/src/components/option/field/PopupPlacementField.tsx index 543f441e..cff35385 100644 --- a/src/components/option/field/PopupPlacementField.tsx +++ b/src/components/option/field/PopupPlacementField.tsx @@ -50,6 +50,13 @@ export const PopupPlacementField = ({ name: 'side', }) + const align = useWatch({ + control: form.control, + name: 'align', + }) + + const isAlignOffsetDisabled = align === ALIGN.center + return (

{t('popupPlacement')}

@@ -161,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, }), From 644b58f3403c9a948cc6bdb000e3b0cbf76f92a2 Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Fri, 16 May 2025 00:27:00 +0900 Subject: [PATCH 3/3] Update: Allow menu position in page settings to inherit from global settings. --- public/_locales/en/messages.json | 6 ++ public/_locales/ja/messages.json | 6 ++ src/components/option/editor/PageRuleList.tsx | 88 +++++++++++-------- src/const.ts | 2 + src/hooks/useSetting.ts | 4 +- src/types.ts | 19 ++-- src/types/schema.ts | 26 +++--- 7 files changed, 93 insertions(+), 58 deletions(-) diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index 1853063f..88c4b5e8 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -197,6 +197,12 @@ "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" }, diff --git a/public/_locales/ja/messages.json b/public/_locales/ja/messages.json index aab3409e..8f423673 100644 --- a/public/_locales/ja/messages.json +++ b/public/_locales/ja/messages.json @@ -197,6 +197,12 @@ "Option_popupPlacement_alignOffset_disabled": { "message": "中央揃えの場合は無効です" }, + "Option_inheritPopupPlacement": { + "message": "メニュー表示位置を全体設定から継承" + }, + "Option_inherit": { + "message": "継承" + }, "Option_mouse_pointer": { "message": "マウスポインタ" }, diff --git a/src/components/option/editor/PageRuleList.tsx b/src/components/option/editor/PageRuleList.tsx index d717e892..6dc61e77 100644 --- a/src/components/option/editor/PageRuleList.tsx +++ b/src/components/option/editor/PageRuleList.tsx @@ -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, @@ -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' @@ -29,9 +28,9 @@ 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' @@ -39,7 +38,10 @@ 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), }) @@ -52,7 +54,7 @@ type pageRulesType = z.infer const DefaultRule = { urlPattern: '', popupEnabled: POPUP_ENABLED.ENABLE, - popupPlacement: PopupPlacement, + popupPlacement: INHERIT as PopupPlacementOrInherit, linkCommandEnabled: LINK_COMMAND_ENABLED.INHERIT, } @@ -145,8 +147,10 @@ export const PageRuleList = ({ {t('popupEnabled')}: {t(`${field.popupEnabled}`)}
  • - {t('popupPlacement')}: {field.popupPlacement.side}{' '} - {field.popupPlacement.align} + {t('popupPlacement')}:{' '} + {field.popupPlacement === INHERIT + ? t('inherit') + : `${field.popupPlacement.side} ${field.popupPlacement.align}`}
  • {t('linkCommandEnabled')}:{' '} @@ -205,7 +209,9 @@ 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, @@ -213,12 +219,19 @@ export const PageRuleDialog = ({ 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]) @@ -267,32 +280,37 @@ export const PageRuleDialog = ({ value: opt, }))} /> - - - +
    + handleInheritChange(e.target.checked)} + className="rounded border-gray-300 cursor-pointer" /> - - {t('labelOther')} - - + {t('inheritPopupPlacement')} + +
    + - - - + + + +
    +
  • @@ -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) })} diff --git a/src/const.ts b/src/const.ts index 9d0bb4ec..9dc81e26 100644 --- a/src/const.ts +++ b/src/const.ts @@ -75,6 +75,8 @@ export enum POPUP_ENABLED { DISABLE = 'Disable', } +export const INHERIT = 'inherit' + export enum LINK_COMMAND_ENABLED { INHERIT = 'Inherit', ENABLE = 'Enable', diff --git a/src/hooks/useSetting.ts b/src/hooks/useSetting.ts index 7ecf35a8..5b2b881a 100644 --- a/src/hooks/useSetting.ts +++ b/src/hooks/useSetting.ts @@ -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 @@ -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 } } diff --git a/src/types.ts b/src/types.ts index 8df76df9..1e35f6da 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,6 +17,7 @@ import type { EXEC_STATE, } from '@/const' import type { PageAction } from '@/services/pageAction' +import { INHERIT } from '@/const' export type DeepPartial = { [P in keyof T]?: T[P] extends object ? DeepPartial : T[P] @@ -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 } @@ -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 } diff --git a/src/types/schema.ts b/src/types/schema.ts index 5203d89d..01e4b77e 100644 --- a/src/types/schema.ts +++ b/src/types/schema.ts @@ -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),