refactor: allow the user to view the fingerprint while the profile is running

This commit is contained in:
zhom
2025-11-29 23:50:54 +04:00
parent dfc8cd4c9f
commit cd8e1dcf18
4 changed files with 56 additions and 22 deletions
+5
View File
@@ -807,6 +807,11 @@ export default function Home() {
}} }}
profile={currentProfileForCamoufoxConfig} profile={currentProfileForCamoufoxConfig}
onSave={handleSaveCamoufoxConfig} onSave={handleSaveCamoufoxConfig}
isRunning={
currentProfileForCamoufoxConfig
? runningProfiles.has(currentProfileForCamoufoxConfig.id)
: false
}
/> />
<GroupManagementDialog <GroupManagementDialog
+18 -12
View File
@@ -19,6 +19,7 @@ interface CamoufoxConfigDialogProps {
onClose: () => void; onClose: () => void;
profile: BrowserProfile | null; profile: BrowserProfile | null;
onSave: (profile: BrowserProfile, config: CamoufoxConfig) => Promise<void>; onSave: (profile: BrowserProfile, config: CamoufoxConfig) => Promise<void>;
isRunning?: boolean;
} }
export function CamoufoxConfigDialog({ export function CamoufoxConfigDialog({
@@ -26,6 +27,7 @@ export function CamoufoxConfigDialog({
onClose, onClose,
profile, profile,
onSave, onSave,
isRunning = false,
}: CamoufoxConfigDialogProps) { }: CamoufoxConfigDialogProps) {
const [config, setConfig] = useState<CamoufoxConfig>({ const [config, setConfig] = useState<CamoufoxConfig>({
geoip: true, geoip: true,
@@ -101,33 +103,37 @@ export function CamoufoxConfigDialog({
return ( return (
<Dialog open={isOpen} onOpenChange={handleClose}> <Dialog open={isOpen} onOpenChange={handleClose}>
<DialogContent className="max-w-3xl max-h-[90vh] flex flex-col"> <DialogContent className="max-w-3xl max-h-[90vh] flex flex-col">
<DialogHeader className="flex-shrink-0"> <DialogHeader className="shrink-0">
<DialogTitle> <DialogTitle>
Configure Fingerprint Settings - {profile.name} {isRunning ? "View" : "Configure"} Fingerprint Settings -{" "}
{profile.name}
</DialogTitle> </DialogTitle>
</DialogHeader> </DialogHeader>
<ScrollArea className="flex-1 h-[320px]"> <ScrollArea className="flex-1 h-[300px]">
<div className="py-4"> <div className="py-4">
<SharedCamoufoxConfigForm <SharedCamoufoxConfigForm
config={config} config={config}
onConfigChange={updateConfig} onConfigChange={updateConfig}
forceAdvanced={true} forceAdvanced={true}
readOnly={isRunning}
/> />
</div> </div>
</ScrollArea> </ScrollArea>
<DialogFooter className="flex-shrink-0 pt-4 border-t"> <DialogFooter className="shrink-0 pt-4 border-t">
<RippleButton variant="outline" onClick={handleClose}> <RippleButton variant="outline" onClick={handleClose}>
Cancel {isRunning ? "Close" : "Cancel"}
</RippleButton> </RippleButton>
<LoadingButton {!isRunning && (
isLoading={isSaving} <LoadingButton
onClick={handleSave} isLoading={isSaving}
disabled={isSaving} onClick={handleSave}
> disabled={isSaving}
Save >
</LoadingButton> Save
</LoadingButton>
)}
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
+1 -2
View File
@@ -1556,9 +1556,8 @@ export function ProfilesDataTable({
onClick={() => { onClick={() => {
meta.onConfigureCamoufox?.(profile); meta.onConfigureCamoufox?.(profile);
}} }}
disabled={isDisabled}
> >
Configure Fingerprint Change Fingerprint
</DropdownMenuItem> </DropdownMenuItem>
)} )}
<DropdownMenuItem <DropdownMenuItem
+32 -8
View File
@@ -23,6 +23,7 @@ interface SharedCamoufoxConfigFormProps {
className?: string; className?: string;
isCreating?: boolean; // Flag to indicate if this is for creating a new profile isCreating?: boolean; // Flag to indicate if this is for creating a new profile
forceAdvanced?: boolean; // Force advanced mode (for editing) forceAdvanced?: boolean; // Force advanced mode (for editing)
readOnly?: boolean; // Flag to indicate if the form should be read-only
} }
// Determine if fingerprint editing should be disabled // Determine if fingerprint editing should be disabled
@@ -35,9 +36,15 @@ interface ObjectEditorProps {
value: Record<string, unknown> | undefined; value: Record<string, unknown> | undefined;
onChange: (value: Record<string, unknown> | undefined) => void; onChange: (value: Record<string, unknown> | undefined) => void;
title: string; title: string;
readOnly?: boolean;
} }
function ObjectEditor({ value, onChange, title }: ObjectEditorProps) { function ObjectEditor({
value,
onChange,
title,
readOnly = false,
}: ObjectEditorProps) {
const [jsonString, setJsonString] = useState(""); const [jsonString, setJsonString] = useState("");
useEffect(() => { useEffect(() => {
@@ -45,6 +52,7 @@ function ObjectEditor({ value, onChange, title }: ObjectEditorProps) {
}, [value]); }, [value]);
const handleChange = (newValue: string) => { const handleChange = (newValue: string) => {
if (readOnly) return;
setJsonString(newValue); setJsonString(newValue);
try { try {
if (newValue.trim() === "" || newValue.trim() === "{}") { if (newValue.trim() === "" || newValue.trim() === "{}") {
@@ -75,6 +83,7 @@ function ObjectEditor({ value, onChange, title }: ObjectEditorProps) {
placeholder={`Enter ${title} as JSON`} placeholder={`Enter ${title} as JSON`}
className="font-mono text-sm" className="font-mono text-sm"
rows={6} rows={6}
disabled={readOnly}
/> />
</div> </div>
); );
@@ -86,6 +95,7 @@ export function SharedCamoufoxConfigForm({
className = "", className = "",
isCreating = false, isCreating = false,
forceAdvanced = false, forceAdvanced = false,
readOnly = false,
}: SharedCamoufoxConfigFormProps) { }: SharedCamoufoxConfigFormProps) {
const [activeTab, setActiveTab] = useState( const [activeTab, setActiveTab] = useState(
forceAdvanced ? "manual" : "automatic", forceAdvanced ? "manual" : "automatic",
@@ -174,7 +184,7 @@ export function SharedCamoufoxConfigForm({
} }
}; };
const isEditingDisabled = isFingerprintEditingDisabled(config); const isEditingDisabled = isFingerprintEditingDisabled(config) || readOnly;
const renderAdvancedForm = () => ( const renderAdvancedForm = () => (
<div className="space-y-6"> <div className="space-y-6">
@@ -187,6 +197,7 @@ export function SharedCamoufoxConfigForm({
onCheckedChange={(checked) => onCheckedChange={(checked) =>
onConfigChange("randomize_fingerprint_on_launch", checked) onConfigChange("randomize_fingerprint_on_launch", checked)
} }
disabled={readOnly}
/> />
<Label htmlFor="randomize-fingerprint" className="font-medium"> <Label htmlFor="randomize-fingerprint" className="font-medium">
Generate random fingerprint on every launch Generate random fingerprint on every launch
@@ -201,9 +212,9 @@ export function SharedCamoufoxConfigForm({
{isEditingDisabled ? ( {isEditingDisabled ? (
<Alert> <Alert>
<AlertDescription> <AlertDescription>
Fingerprint editing is disabled because random fingerprint {readOnly
generation is enabled. Disable the option above to manually edit the ? "Fingerprint editing is disabled because the profile is currently running. Stop the profile to make changes."
fingerprint configuration. : "Fingerprint editing is disabled because random fingerprint generation is enabled. Disable the option above to manually edit the fingerprint configuration."}
</AlertDescription> </AlertDescription>
</Alert> </Alert>
) : ( ) : (
@@ -727,6 +738,7 @@ export function SharedCamoufoxConfigForm({
updateFingerprintConfig("webGl:parameters", value) updateFingerprintConfig("webGl:parameters", value)
} }
title="WebGL Parameters" title="WebGL Parameters"
readOnly={readOnly}
/> />
</div> </div>
@@ -743,6 +755,7 @@ export function SharedCamoufoxConfigForm({
updateFingerprintConfig("webGl2:parameters", value) updateFingerprintConfig("webGl2:parameters", value)
} }
title="WebGL2 Parameters" title="WebGL2 Parameters"
readOnly={readOnly}
/> />
</div> </div>
@@ -759,6 +772,7 @@ export function SharedCamoufoxConfigForm({
updateFingerprintConfig("webGl:shaderPrecisionFormats", value) updateFingerprintConfig("webGl:shaderPrecisionFormats", value)
} }
title="WebGL Shader Precision Formats" title="WebGL Shader Precision Formats"
readOnly={readOnly}
/> />
</div> </div>
@@ -775,6 +789,7 @@ export function SharedCamoufoxConfigForm({
updateFingerprintConfig("webGl2:shaderPrecisionFormats", value) updateFingerprintConfig("webGl2:shaderPrecisionFormats", value)
} }
title="WebGL2 Shader Precision Formats" title="WebGL2 Shader Precision Formats"
readOnly={readOnly}
/> />
</div> </div>
@@ -876,10 +891,18 @@ export function SharedCamoufoxConfigForm({
// Advanced mode only (for editing) // Advanced mode only (for editing)
renderAdvancedForm() renderAdvancedForm()
) : ( ) : (
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full"> <Tabs
value={activeTab}
onValueChange={readOnly ? undefined : setActiveTab}
className="w-full"
>
<TabsList className="grid grid-cols-2 w-full"> <TabsList className="grid grid-cols-2 w-full">
<TabsTrigger value="automatic">Automatic</TabsTrigger> <TabsTrigger value="automatic" disabled={readOnly}>
<TabsTrigger value="manual">Manual</TabsTrigger> Automatic
</TabsTrigger>
<TabsTrigger value="manual" disabled={readOnly}>
Manual
</TabsTrigger>
</TabsList> </TabsList>
<TabsContent value="automatic" className="space-y-6"> <TabsContent value="automatic" className="space-y-6">
@@ -892,6 +915,7 @@ export function SharedCamoufoxConfigForm({
onCheckedChange={(checked) => onCheckedChange={(checked) =>
onConfigChange("randomize_fingerprint_on_launch", checked) onConfigChange("randomize_fingerprint_on_launch", checked)
} }
disabled={readOnly}
/> />
<Label <Label
htmlFor="randomize-fingerprint-auto" htmlFor="randomize-fingerprint-auto"