Skip to content

Commit

Permalink
feat: sidepanel permission
Browse files Browse the repository at this point in the history
  • Loading branch information
rowthan committed May 27, 2024
1 parent 9fd9505 commit d281878
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 56 deletions.
42 changes: 42 additions & 0 deletions apps/web/@/components/ui/radio-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from "react"
import { CheckIcon } from "@radix-ui/react-icons"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"

import { cn } from "@/utils"

const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Root
className={cn("grid gap-2", className)}
{...props}
ref={ref}
/>
)
})
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName

const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<CheckIcon className="h-3.5 w-3.5 fill-primary" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
)
})
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName

export { RadioGroup, RadioGroupItem }
80 changes: 61 additions & 19 deletions apps/web/components/FooterSetting.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {type ReactNode} from 'react';
import {MdOutlineLiveHelp} from "react-icons/md";
import React, {type ReactNode} from 'react';
import {
Popover,
PopoverContent,
Expand All @@ -14,37 +13,64 @@ import ActionButton from "./button/ActionButton";
import useTabPagenoteState from "../hooks/useTabPagenoteState";
import useCurrentTab from "../hooks/useCurrentTab";
import extApi from "@pagenote/shared/lib/pagenote-api";
import useWhoAmi from "../hooks/useWhoAmi";
import usePermissions from "../hooks/usePermissions";
import { toast } from '@/components/ui/use-toast'
import {ToastAction} from "../@/components/ui/toast";

interface Props {
children?: ReactNode;
}

export function PopSetting() {
export function PopPanelSetting(props:{closedAfterChange: boolean}){
const [config,update] = useSettingConfig<{popMode?:'panel'|'popup'}>('extension')
const isSidePanel = config?.popMode === 'panel';
const {pathname} = useRouter();
const isSidePanelInPath = pathname.includes('sidepanel');
const {tab} = useCurrentTab();
const [permission,requestPermission] = usePermissions();
const [whoAmI] = useWhoAmi();

function updateMode(mode: 'popup'|'panel') {
function updateMode(mode: 'popup' | 'panel') {
update({
popMode: mode,
}).then(function () {
if(mode==='popup' && isSidePanelInPath){
window.close();
if (mode === 'popup' && isSidePanelInPath) {
if(props.closedAfterChange){
window.close();
}
}
if(mode==='panel' && !isSidePanelInPath){
window.close();
if (mode === 'panel' && !isSidePanelInPath) {
if(!permission?.permissions?.includes('sidePanel')){
// 请求权限
toast({
variant: "destructive",
title: "缺少必要的授权",
description: "你需要授权后可启用侧边栏模式",
action: <ToastAction altText="Try again" onClick={()=>{
requestPermission({
permissions: ['sidePanel']
})
}}>授权</ToastAction>,
})
}
if(props.closedAfterChange){
window.close();
}
tab?.id && chrome && chrome.sidePanel && chrome.sidePanel.open({
tabId: tab?.id
})
}
})
}

return (
<div className={'flex flex-col min-w-[120px]'}>
<button className={'flex justify-between hover:bg-accent px-2 py-1'}
if(whoAmI?.isFirefox){
return null;
}

return(
<>
<button className={'flex w-full justify-between hover:bg-accent px-2 py-1'}
onClick={() => {
updateMode('popup')
}}
Expand All @@ -54,7 +80,7 @@ export function PopSetting() {
!isSidePanel && <FaCheck/>
}
</button>
<button className={'flex justify-between hover:bg-accent px-2 py-1'}
<button className={'flex w-full justify-between hover:bg-accent px-2 py-1'}
onClick={() => {
updateMode('panel')
}}
Expand All @@ -64,6 +90,15 @@ export function PopSetting() {
isSidePanel && <FaCheck/>
}
</button>
</>
)

}

export function PopSetting() {
return (
<div className={'flex flex-col min-w-[120px]'}>
<PopPanelSetting closedAfterChange={true} />
<a href={`${basePath}/ext/setting.html`} target={'_blank'} className={'hover:bg-accent px-2 py-1'}>
更多设置
</a>
Expand All @@ -74,7 +109,7 @@ export function PopSetting() {
export default function FooterSetting(props: Props) {
const [tabState, mutate, isLoading] = useTabPagenoteState()
const { tab } = useCurrentTab()

const [whoAmI] = useWhoAmi()
function enableCopy() {
if (tabState?.enabledCopy) {
return
Expand Down Expand Up @@ -103,12 +138,19 @@ export default function FooterSetting(props: Props) {
</ActionButton>
</div>
<div className={'text-sm text-muted-foreground'}>
<Popover>
<PopoverTrigger>常用设置</PopoverTrigger>
<PopoverContent className={'text-sm p-0'}>
<PopSetting />
</PopoverContent>
</Popover>
{
whoAmI?.isFirefox ?
<a href={`${basePath}/ext/setting.html`} target={'_blank'}
className={'hover:bg-accent px-2 py-1'}>
设置
</a> :
<Popover>
<PopoverTrigger>常用设置</PopoverTrigger>
<PopoverContent className={'text-sm p-0'}>
<PopSetting/>
</PopoverContent>
</Popover>
}
</div>
</div>
);
Expand Down
19 changes: 11 additions & 8 deletions apps/web/components/HelpAside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@ export default function HelpAside(props: Props) {
aria-label={'help'}>
<MdOutlineLiveHelp className={'fill-current text-xl'}/>
</a>
<Popover>
<PopoverTrigger>
<AiOutlineSetting className={'fill-current text-xl'}/>
</PopoverTrigger>
<PopoverContent className={'text-sm p-0'}>
<PopSetting/>
</PopoverContent>
</Popover>
<a href="https://pagenote.cn/setting">
<AiOutlineSetting className={'fill-current text-xl'}/>
</a>
{/*<Popover>*/}
{/* <PopoverTrigger>*/}
{/* <AiOutlineSetting className={'fill-current text-xl'}/>*/}
{/* </PopoverTrigger>*/}
{/* <PopoverContent className={'text-sm p-0'}>*/}
{/* <PopSetting/>*/}
{/* </PopoverContent>*/}
{/*</Popover>*/}
</div>
</aside>
<div className={'sm:hidden block'}>
Expand Down
33 changes: 27 additions & 6 deletions apps/web/components/permission/PermissionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,46 @@ import { HiCheckCircle } from "react-icons/hi";
import { PiProhibitFill } from "react-icons/pi";
import useWhoAmi from "hooks/useWhoAmi";
import usePermissions from "hooks/usePermissions";
import { TbLayoutSidebarRightCollapseFilled } from "react-icons/tb";
import { FcTemplate } from "react-icons/fc";
import { FcBookmark } from "react-icons/fc";
import { FaInternetExplorer } from "react-icons/fa6";

interface Props {
children?: ReactNode;
}

const permissionList = [
{
name: '【必须】访问所有网站',
name: '访问所有网站[必须]',
description: '在所有网页上运行工作的必要权限',
namespace: 'origins',
permission: '<all_urls>',
badge: <FaInternetExplorer fill={'#39b3df'} />
},
{
name: '【可选】标签页分组管理',
description: '可以对网页进行归组管理',
name: '标签页分组管理',
description: '自动将同类标签页归类至同组,批量管理',
permission: 'tabGroups',
namespace: 'permissions',
supportPlatform: ['chrome','edge','offline']
}
supportPlatform: ['chrome','edge','offline'],
badge: <FcTemplate />
},
{
name: '侧边栏模式',
description: '以侧边栏代替弹层',
namespace: 'permissions',
permission: 'sidePanel',
supportPlatform: ['chrome','edge','offline'],
badge: <TbLayoutSidebarRightCollapseFilled />
},
{
name: '书签管理',
description: '允许访问和修改浏览器书签',
namespace: 'permissions',
permission: 'bookmarks',
badge: <FcBookmark />
},
]

export default function PermissionList(props: Props) {
Expand All @@ -43,8 +64,8 @@ export default function PermissionList(props: Props) {
const hasPerm = permission[item.namespace]?.includes(item.permission);
return (
<BasicSettingLine
badge={item.badge}
onClick={()=>{
console.log('request');
if(hasPerm){
return
}
Expand Down
18 changes: 18 additions & 0 deletions apps/web/components/setting/LightSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import {
AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import useWhoAmi from "../../hooks/useWhoAmi";
import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import {PopPanelSetting} from "../FooterSetting";


export default function LightSetting() {
const { data: setting, update: updateSetting } = useSettings()
Expand Down Expand Up @@ -86,6 +90,20 @@ export default function LightSetting() {
</div>
}
></BasicSettingLine>

{
!whoAmI?.isFirefox &&
<BasicSettingLine
label={'面板模式'}
className={'cursor-pointer'}
subLabel={'辅助面板展示形式'}
right={
<div className={'flex-col gap-1 min-w-32'}>
<PopPanelSetting closedAfterChange={false} />
</div>
}
/>
}
</SettingSection>

<div>
Expand Down
27 changes: 10 additions & 17 deletions apps/web/hooks/useCurrentTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import extApi from "@pagenote/shared/lib/pagenote-api";
import useSWR from "swr";
import Tab = chrome.tabs.Tab;
import {useEffect} from "react";
import {callChrome} from "../utils/chrome";
import {callChrome, checkInExtensionContext} from "../utils/chrome";

type TabGroups = Tab[];
type WindowMap = Map<number, TabGroups>
Expand All @@ -21,7 +21,7 @@ export default function useCurrentTab():{tab: Tab | undefined, windows: TabGroup
)

useEffect(function () {
if(chrome && chrome.tabs){
if(checkInExtensionContext() && chrome.tabs){
chrome.tabs.onActivated.addListener(function () {
mutate();
})
Expand Down Expand Up @@ -64,21 +64,14 @@ export default function useCurrentTab():{tab: Tab | undefined, windows: TabGroup

const tabId = isNaN(Number(currentTabId)) ? currentTabId : Number(currentTabId)


if(chrome && chrome.tabs){
return chrome.tabs.get(tabId as number).then(function(res){
return res;
})
}else{
return callChrome<Tab>({
method: 'get',
namespace: 'tabs',
arguments: [tabId],
})
.then(function (res) {
return res
})
}
return callChrome<Tab>({
method: 'get',
namespace: 'tabs',
arguments: [tabId],
})
.then(function (res) {
return res
})
}

function getAllWindows() {
Expand Down
3 changes: 2 additions & 1 deletion apps/web/hooks/useTabPagenoteState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import useSWR from 'swr'
import extApi from '@pagenote/shared/lib/pagenote-api'
import { useEffect } from 'react'
import useCurrentTab from "./useCurrentTab";
import {checkInExtensionContext} from "../utils/chrome";

function fetchStatus(tabId?: number) {
console.log('fetch tab status',tabId)
Expand Down Expand Up @@ -46,7 +47,7 @@ export default function useTabPagenoteState(): [TabState | undefined, () => void
)

useEffect(() => {
if(chrome && chrome.tabs){
if(checkInExtensionContext()){
chrome.tabs.onActivated.addListener(function () {
mutate();
})
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-toast": "^1.1.4",
"@radix-ui/react-tooltip": "^1.0.6",
"@radix-ui/react-radio-group": "^1.0.3",
"@texonom/nclient": "^1.2.11",
"@tiptap/extension-color": "^2.3.0",
"@tiptap/extension-image": "^2.3.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/pages/ext/sidepanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PopupPage from "./popup";

export default function sidepanel() {
return (
<PopupPage className={'!min-w-[250px]'} />
<PopupPage className={'!min-w-[250px] side-panel'} />
);
}

Loading

0 comments on commit d281878

Please sign in to comment.