-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from chakkun1121/feature/make-right-click-menu
close #32
- Loading branch information
Showing
7 changed files
with
237 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
export type serverSettingsType = {}; | ||
export type serverSettingsType = { | ||
customSearch: { | ||
name: string; | ||
url: string; //検索キーワードが%sに入る | ||
}[]; | ||
}; | ||
export type localSettings = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
"use client"; | ||
|
||
import { usePathname, useSearchParams } from "next/navigation"; | ||
import { useEffect, useState } from "react"; | ||
type menuInfo = { | ||
[key: string]: menuInfoOptions[]; | ||
}; | ||
type menuInfoOptions = { | ||
name: { | ||
ja: string; | ||
en: string; | ||
}; | ||
onclick?: (text: string) => void; | ||
options?: menuInfoOptions[]; | ||
when?: { | ||
onSelected?: boolean; | ||
path?: string[]; | ||
}; | ||
}; | ||
export default function RightClick() { | ||
const [isShow, setIsShow] = useState(false); | ||
const [x, setX] = useState(0); | ||
const [y, setY] = useState(0); | ||
const pathName = usePathname(); | ||
const searchParams = useSearchParams(); | ||
const menu: menuInfoOptions[] = [ | ||
{ | ||
name: { | ||
ja: "コピー", | ||
en: "Copy", | ||
}, | ||
onclick: (text: string) => { | ||
navigator.clipboard.writeText(text); | ||
}, | ||
when: { onSelected: true }, | ||
}, | ||
{ | ||
name: { | ||
ja: "読み上げ", | ||
en: "speech", | ||
}, | ||
onclick: (text: string) => { | ||
const utterance = new SpeechSynthesisUtterance(text); | ||
utterance.lang = "en-US"; | ||
speechSynthesis.speak(utterance); | ||
}, | ||
when: { onSelected: true }, | ||
}, | ||
{ | ||
name: { | ||
ja: "で検索", | ||
en: "Search with", | ||
}, | ||
options: [ | ||
{ | ||
name: { | ||
ja: "Google", | ||
en: "Google", | ||
}, | ||
onclick: (text: string) => { | ||
window.open(`https://www.google.com/search?q=${text}`, "_blank"); | ||
}, | ||
}, | ||
{ | ||
name: { | ||
ja: "Google翻訳", | ||
en: "Google Translate", | ||
}, | ||
onclick: (text: string) => { | ||
window.open( | ||
`https://translate.google.com/?sl=auto&tl=auto&text=${text}&op=translate`, | ||
"_blank" | ||
); | ||
}, | ||
}, | ||
// { | ||
// name: { | ||
// ja: "+追加", | ||
// en: "+add", | ||
// }, | ||
// onclick: () => { | ||
// window.open("/settings#dictionaries", "_blank"); | ||
// }, | ||
// }, | ||
], | ||
when: { onSelected: true }, | ||
}, | ||
{ | ||
name: { | ||
ja: "印刷", | ||
en: "print", | ||
}, | ||
onclick: () => { | ||
window.open(`/print?fileId=${searchParams.get("fileId")}`, "_blank"); | ||
}, | ||
}, | ||
{ | ||
name: { | ||
ja: "ヘルプ", | ||
en: "Help", | ||
}, | ||
onclick: () => { | ||
window.open("/help", "_blank"); | ||
}, | ||
}, | ||
// { | ||
// name: { | ||
// ja: "設定", | ||
// en: "settings", | ||
// }, | ||
// onclick: () => { | ||
// window.open("/settings", "_blank"); | ||
// }, | ||
// }, | ||
]; | ||
|
||
useEffect(() => { | ||
window.addEventListener("contextmenu", (e) => { | ||
e.preventDefault(); | ||
setX(e.clientX); | ||
setY(e.clientY); | ||
setIsShow(true); | ||
}); | ||
window.addEventListener("click", () => setIsShow(false)); | ||
}); | ||
const onSelected = !!window.getSelection()?.toString(); | ||
const currentMenu = menu.filter((e) => { | ||
if (e.when?.onSelected && !onSelected) return false; | ||
if (e.when?.path && !e.when.path.includes(pathName)) return false; | ||
return true; | ||
}); | ||
return ( | ||
<> | ||
{isShow && ( | ||
<> | ||
<div | ||
className="absolute top-0 left-0 w-64 bg-gray-100 rounded shadow-lg z-50 select-none" | ||
style={{ | ||
top: y, | ||
left: x, | ||
}} | ||
> | ||
{currentMenu.map((e) => ( | ||
<MenuButton menuInfo={e} key={e.name.en} x={x} /> | ||
))} | ||
</div> | ||
</> | ||
)} | ||
</> | ||
); | ||
} | ||
function MenuButton({ menuInfo, x }: { menuInfo: menuInfoOptions; x: number }) { | ||
return menuInfo.options ? ( | ||
<> | ||
<p className="w-full h-12 px-4 text-left hover:bg-gray-200 text-button flex items-center group after:content-['>'] justify-between after:text-gray-500"> | ||
{menuInfo.name["ja"]} | ||
<div className="absolute w-64 bg-gray-100 rounded shadow-lg z-50 hidden group-hover:block left-64"> | ||
{menuInfo.options.map((e) => ( | ||
<MenuButton menuInfo={e} key={e.name.en} x={x + 256} /> | ||
))} | ||
</div> | ||
</p> | ||
</> | ||
) : ( | ||
<button | ||
className="w-full h-12 px-4 text-left hover:bg-gray-200" | ||
onClick={() => { | ||
menuInfo.onclick?.(window.getSelection()?.toString() || ""); | ||
}} | ||
> | ||
{menuInfo.name["ja"]} | ||
</button> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
"use client"; | ||
|
||
import { customSession } from "@/@types/customSession"; | ||
import { localSettings } from "@/@types/settings"; | ||
import { useSession } from "next-auth/react"; | ||
import { atom, useRecoilState } from "recoil"; | ||
import { recoilPersist } from "recoil-persist"; | ||
import { useServerSettings } from "../_library/settings/useServerSettings"; | ||
|
||
export default function Settings() { | ||
const { data: session }: { data: customSession | null } = | ||
useSession() as unknown as { data: customSession }; | ||
const token = session?.accessToken; | ||
const { serverSettings, setServerSettings, isLoading, isSaving } = | ||
useServerSettings(token); | ||
if (isLoading) return <p className="text-center">loading...</p>; | ||
return <div></div>; | ||
} | ||
// recoil | ||
const { persistAtom } = recoilPersist({ | ||
key: "settings", | ||
storage: typeof window === "undefined" ? undefined : localStorage, | ||
}); | ||
export const localSettingsState = atom<localSettings>({ | ||
key: "settings", | ||
default: {}, | ||
effects_UNSTABLE: [persistAtom], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { Metadata } from "next"; | ||
import Settings from "./main"; | ||
|
||
export default function Page() { | ||
return <Settings />; | ||
} | ||
export const metadata: Metadata = { | ||
title: "設定", | ||
description: "VocabPhraseの設定ページです。", | ||
robots: "noindex", | ||
}; |
This file was deleted.
Oops, something went wrong.