-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(shortcuts): add support for disabling keyboard shortcuts on spec…
…ific sites - Introduced BlockConfig utility to manage shortcut disabling for specific websites - Added SHORTCUT_DISABLED_PAGES configuration in preferences - Implemented shortcut blocking mechanism with URL pattern matching - Enhanced AskPanel and background script to handle shortcut-specific behaviors - Added Notification component for user feedback on disabled shortcuts
- Loading branch information
Showing
9 changed files
with
208 additions
and
23 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
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,30 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
|
||
interface NotificationProps { | ||
message: string; | ||
duration?: number; | ||
onClose?: () => void; | ||
} | ||
|
||
export default function Notification({ message, duration = 3000, onClose }: NotificationProps) { | ||
const [isVisible, setIsVisible] = useState(true); | ||
|
||
useEffect(() => { | ||
const timer = setTimeout(() => { | ||
setIsVisible(false); | ||
onClose?.(); | ||
}, duration); | ||
|
||
return () => clearTimeout(timer); | ||
}, [duration, onClose]); | ||
|
||
if (!isVisible) return null; | ||
|
||
return ( | ||
<div | ||
className="fixed top-4 right-4 bg-black text-white px-4 py-2 rounded-lg shadow-lg opacity-90 transition-opacity duration-200" | ||
style={{ zIndex: 2147483647 }}> | ||
{message} | ||
</div> | ||
); | ||
} |
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
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,64 @@ | ||
import { StorageManager } from './StorageManager'; | ||
|
||
export class BlockConfig { | ||
private static instance: BlockConfig; | ||
private patterns: string[] = []; | ||
|
||
private constructor() {} | ||
|
||
public static getInstance(): BlockConfig { | ||
if (!BlockConfig.instance) { | ||
BlockConfig.instance = new BlockConfig(); | ||
} | ||
return BlockConfig.instance; | ||
} | ||
|
||
public async initialize(): Promise<void> { | ||
try { | ||
const preferences = await StorageManager.getUserPreferences(); | ||
// 从用户配置中读取禁用快捷键的页面列表 | ||
this.patterns = preferences.SHORTCUT_DISABLED_PAGES; | ||
} catch (error) { | ||
console.error('Failed to initialize BlockConfig:', error); | ||
// 使用默认模式 | ||
this.patterns = [ | ||
'feishu.cn', // 默认在飞书页面禁用快捷键 | ||
]; | ||
} | ||
} | ||
|
||
public isShortcutDisabled(url: string): boolean { | ||
if (!url) return false; | ||
const currentDomain = new window.URL(url).hostname; | ||
|
||
return this.patterns.some(pattern => { | ||
// 检查完整 URL 匹配 | ||
if (pattern.startsWith('http') && url.startsWith(pattern)) { | ||
return true; | ||
} | ||
// 检查域名匹配 | ||
if (!pattern.includes('/') && currentDomain.includes(pattern)) { | ||
return true; | ||
} | ||
// 检查通配符模式 | ||
if (pattern.includes('*')) { | ||
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); | ||
return regex.test(url); | ||
} | ||
return false; | ||
}); | ||
} | ||
|
||
public async savePatterns(patterns: string[]): Promise<void> { | ||
this.patterns = patterns; | ||
const preferences = await StorageManager.getUserPreferences(); | ||
await StorageManager.saveUserPreferences({ | ||
...preferences, | ||
SHORTCUT_DISABLED_PAGES: patterns, | ||
}); | ||
} | ||
|
||
public getPatterns(): string[] { | ||
return this.patterns; | ||
} | ||
} |
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