diff --git a/src/components/settings/SettingsNavigation.tsx b/src/components/settings/SettingsNavigation.tsx index d56be977..104e954e 100644 --- a/src/components/settings/SettingsNavigation.tsx +++ b/src/components/settings/SettingsNavigation.tsx @@ -93,12 +93,6 @@ const settingsTabs: SettingsTab[] = [ icon: , path: '/settings/ollama' }, - { - key: 'xnostr', - label: 'XNostr', - icon: , - path: '/settings/xnostr' - }, { key: 'relay_info', label: 'Relay Info', diff --git a/src/components/settings/SettingsPage.tsx b/src/components/settings/SettingsPage.tsx index 7e91026f..dca692b2 100644 --- a/src/components/settings/SettingsPage.tsx +++ b/src/components/settings/SettingsPage.tsx @@ -7,7 +7,6 @@ import { PictureOutlined, ApiOutlined, RobotOutlined, - TwitterOutlined, InfoCircleOutlined, WalletOutlined, GlobalOutlined, @@ -23,7 +22,6 @@ import WalletSettings from './WalletSettings'; import GeneralSettings from './GeneralSettings'; import RelayInfoSettings from './RelayInfoSettings'; import QueryCacheSettings from './QueryCacheSettings'; -import XNostrSettings from './XNostrSettings'; const SettingsContainer = styled.div` width: 100%; @@ -175,13 +173,6 @@ const SettingsPage: React.FC = () => { icon: , component: }, - { - key: 'xnostr', - path: '/settings/xnostr', - label: 'XNostr', - icon: , - component: - }, { key: 'relay_info', path: '/settings/relay-info', diff --git a/src/components/settings/XNostrSettings.tsx b/src/components/settings/XNostrSettings.tsx deleted file mode 100644 index 3a801069..00000000 --- a/src/components/settings/XNostrSettings.tsx +++ /dev/null @@ -1,611 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Form, Input, InputNumber, Switch, Tooltip, Button, Space, Divider, Collapse } from 'antd'; -import { - QuestionCircleOutlined, - PlusOutlined, - DeleteOutlined, - TwitterOutlined, - FolderOutlined, - ClockCircleOutlined, - TeamOutlined -} from '@ant-design/icons'; -import useGenericSettings from '@app/hooks/useGenericSettings'; -import { SettingsGroupType, XNostrNitterInstance, XNostrNitterSettings, XNostrIntervalSettings } from '@app/types/settings.types'; -import type { XNostrSettings as XNostrSettingsType } from '@app/types/settings.types'; -import BaseSettingsForm from './BaseSettingsForm'; -import styled from 'styled-components'; - -const { Panel } = Collapse; - -const NitterInstanceContainer = styled.div` - margin-bottom: 16px; - padding: 16px; - border: 1px solid #f0f0f0; - border-radius: 4px; - background-color: #fafafa; -`; - -const XNostrSettingsComponent: React.FC = () => { - const { - settings, - loading, - error, - fetchSettings, - updateSettings: updateSettingsGeneric, - saveSettings, - } = useGenericSettings('xnostr'); - - // Create a typed wrapper for updateSettings - const updateSettings = (updatedSettings: Partial>) => { - updateSettingsGeneric(updatedSettings); - }; - - const [form] = Form.useForm(); - const [nitterInstances, setNitterInstances] = useState([]); - const [isUserEditing, setIsUserEditing] = useState(false); - - // Update form values when settings change, but only if user isn't actively editing - useEffect(() => { - if (settings && !isUserEditing) { - console.log('XNostrSettings - Received settings:', settings); - - // Transform property names to match form field names - // The API returns properties without the prefix, but the form expects prefixed names - const settingsObj = settings as Record; - - // Create a transformed settings object with prefixed property names - const formValues = { - xnostr_enabled: settingsObj.enabled, - xnostr_browser_path: settingsObj.browser_path, - xnostr_browser_pool_size: typeof settingsObj.browser_pool_size === 'string' - ? parseInt(settingsObj.browser_pool_size) - : settingsObj.browser_pool_size, - xnostr_check_interval: typeof settingsObj.check_interval === 'string' - ? parseInt(settingsObj.check_interval) - : settingsObj.check_interval, - xnostr_concurrency: typeof settingsObj.concurrency === 'string' - ? parseInt(settingsObj.concurrency) - : settingsObj.concurrency, - xnostr_temp_dir: settingsObj.temp_dir, - xnostr_update_interval: typeof settingsObj.update_interval === 'string' - ? parseInt(settingsObj.update_interval) - : settingsObj.update_interval, - // Handle nested objects - xnostr_verification_intervals: settingsObj.verification_intervals || {}, - // Don't set nitter instances here, we'll handle them separately - }; - - console.log('XNostrSettings - Transformed form values:', formValues); - - // Set form values with a slight delay to ensure the form is ready - setTimeout(() => { - form.setFieldsValue(formValues); - console.log('XNostrSettings - Form values after set:', form.getFieldsValue()); - }, 100); - - // Set nitter instances - if (settingsObj.nitter?.instances) { - setNitterInstances(settingsObj.nitter.instances); - } else { - setNitterInstances([]); - } - } - }, [settings, form, isUserEditing]); - - // Handle form value changes - const handleValuesChange = (changedValues: Record) => { - setIsUserEditing(true); // Mark that user is currently editing - - // Don't use updateSettings directly with form values - // Instead, update the form values and let the form handle the state - - // We'll handle specific nested object updates in the other functions - // This function is just for the form's onValuesChange callback - - // For simple fields, we can update them directly - const simpleChanges: Partial = {}; - - // Only include simple fields (not nested objects) - if ('xnostr_enabled' in changedValues) { - simpleChanges.xnostr_enabled = changedValues.xnostr_enabled; - } - if ('xnostr_browser_path' in changedValues) { - simpleChanges.xnostr_browser_path = changedValues.xnostr_browser_path; - } - if ('xnostr_browser_pool_size' in changedValues) { - simpleChanges.xnostr_browser_pool_size = changedValues.xnostr_browser_pool_size; - } - if ('xnostr_check_interval' in changedValues) { - simpleChanges.xnostr_check_interval = changedValues.xnostr_check_interval; - } - if ('xnostr_concurrency' in changedValues) { - simpleChanges.xnostr_concurrency = changedValues.xnostr_concurrency; - } - if ('xnostr_temp_dir' in changedValues) { - simpleChanges.xnostr_temp_dir = changedValues.xnostr_temp_dir; - } - if ('xnostr_update_interval' in changedValues) { - simpleChanges.xnostr_update_interval = changedValues.xnostr_update_interval; - } - - // Only update if we have changes - if (Object.keys(simpleChanges).length > 0) { - updateSettings(simpleChanges); - } - }; - - // Add a new nitter instance - const handleAddNitterInstance = () => { - setIsUserEditing(true); // Mark that user is currently editing - - const newInstance: XNostrNitterInstance = { - priority: nitterInstances.length + 1, - url: '' - }; - - const newInstances = [...nitterInstances, newInstance]; - setNitterInstances(newInstances); - - // Update settings with new instances - const updatedSettings = { ...settings }; - if (!updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter = { - failure_threshold: 3, - recovery_threshold: 2, - requests_per_minute: 10, - instances: [] - }; - } - updatedSettings.xnostr_nitter.instances = newInstances; - updateSettings(updatedSettings); - }; - - // Remove a nitter instance - const handleRemoveNitterInstance = (index: number) => { - setIsUserEditing(true); // Mark that user is currently editing - - const newInstances = [...nitterInstances]; - newInstances.splice(index, 1); - - // Update priorities - newInstances.forEach((instance, idx) => { - instance.priority = idx + 1; - }); - - setNitterInstances(newInstances); - - // Update settings with new instances - const updatedSettings = { ...settings }; - if (updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter.instances = newInstances; - updateSettings(updatedSettings); - } - }; - - // Update a nitter instance - const handleUpdateNitterInstance = (index: number, field: keyof XNostrNitterInstance, value: number | string | null) => { - setIsUserEditing(true); // Mark that user is currently editing - - const newInstances = [...nitterInstances]; - - // Handle null values from InputNumber - if (value === null && field === 'priority') { - value = 0; // Default to 0 for null number values - } - - // Use a more specific type assertion based on the field - if (field === 'priority') { - newInstances[index].priority = value as number; - } else if (field === 'url') { - newInstances[index].url = value as string; - } - setNitterInstances(newInstances); - - // Update settings with new instances - const updatedSettings = { ...settings }; - if (updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter.instances = newInstances; - updateSettings(updatedSettings); - } - }; - - // Update nitter settings - const handleNitterSettingsChange = (field: keyof XNostrNitterSettings, value: number | null) => { - setIsUserEditing(true); // Mark that user is currently editing - - // Handle null values from InputNumber - if (value === null) { - value = 0; // Default to 0 for null number values - } - const updatedSettings = { ...settings }; - if (!updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter = { - failure_threshold: 3, - recovery_threshold: 2, - requests_per_minute: 10, - instances: nitterInstances - }; - } - - updatedSettings.xnostr_nitter = { - ...updatedSettings.xnostr_nitter, - [field]: value - }; - updateSettings(updatedSettings); - }; - - // Update verification interval settings - const handleIntervalSettingsChange = (field: keyof XNostrIntervalSettings, value: number | null) => { - setIsUserEditing(true); // Mark that user is currently editing - - // Handle null values from InputNumber - if (value === null) { - value = 0; // Default to 0 for null number values - } - const updatedSettings = { ...settings }; - if (!updatedSettings.xnostr_verification_intervals) { - updatedSettings.xnostr_verification_intervals = { - follower_update_interval_days: 7, - full_verification_interval_days: 30, - max_verification_attempts: 5 - }; - } - - updatedSettings.xnostr_verification_intervals = { - ...updatedSettings.xnostr_verification_intervals, - [field]: value - }; - updateSettings(updatedSettings); - }; - - // Modified save function to reset the editing flag - const handleSave = async () => { - await saveSettings(); - setIsUserEditing(false); // Reset after saving - }; - - return ( - { - fetchSettings(); - setIsUserEditing(false); - }} - > -
{ - console.log('Form submitted with values:', values); - setIsUserEditing(false); - }} - > - {/* General XNostr Settings */} - - Enable XNostr  - - - - - } - valuePropName="checked" - > - - - - - Browser Path  - - - - - } - > - } - placeholder="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" - /> - - - - Browser Pool Size  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Temporary Directory  - - - - - } - > - } - placeholder="/tmp/xnostr-verification" - /> - - - - Check Interval (seconds)  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - } - min={1} - style={{ width: '100%' }} - /> - - - - Concurrency  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - } - min={1} - style={{ width: '100%' }} - /> - - - - Update Interval (hours)  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - } - min={1} - style={{ width: '100%' }} - /> - - - Nitter Settings - - {/* Nitter Settings */} - - Failure Threshold  - - - - - } - > - handleNitterSettingsChange('failure_threshold', value)} - min={1} - style={{ width: '100%' }} - /> - - - - Recovery Threshold  - - - - - } - > - handleNitterSettingsChange('recovery_threshold', value)} - min={1} - style={{ width: '100%' }} - /> - - - - Requests Per Minute  - - - - - } - > - handleNitterSettingsChange('requests_per_minute', value)} - min={1} - style={{ width: '100%' }} - /> - - - - Nitter Instances  - - - - - } - > - {nitterInstances.map((instance, index) => ( - - - - handleUpdateNitterInstance(index, 'priority', value)} - min={1} - style={{ width: '100%' }} - /> - - - - handleUpdateNitterInstance(index, 'url', e.target.value)} - placeholder="https://nitter.net/" - prefix={} - /> - - - - - - ))} - - - - - Verification Intervals - - {/* Verification Interval Settings */} - - Follower Update Interval (days)  - - - - - } - > - handleIntervalSettingsChange('follower_update_interval_days', value)} - min={1} - style={{ width: '100%' }} - /> - - - - Full Verification Interval (days)  - - - - - } - > - handleIntervalSettingsChange('full_verification_interval_days', value)} - min={1} - style={{ width: '100%' }} - /> - - - - Max Verification Attempts  - - - - - } - > - handleIntervalSettingsChange('max_verification_attempts', value)} - min={1} - style={{ width: '100%' }} - /> - - - -

- Note: XNostr is used for Twitter verification of Nostr profiles. It requires a browser to be installed and accessible. - The Nitter instances are used to scrape Twitter profiles when the Twitter API is not available. -

-
-
-
- ); -}; - -// Export the component as a named export and as the default export -export { XNostrSettingsComponent as XNostrSettings }; -export default XNostrSettingsComponent; diff --git a/src/components/settings/layouts/AdvancedSettingsLayout.tsx b/src/components/settings/layouts/AdvancedSettingsLayout.tsx index 4777fa83..0ecf5fee 100644 --- a/src/components/settings/layouts/AdvancedSettingsLayout.tsx +++ b/src/components/settings/layouts/AdvancedSettingsLayout.tsx @@ -9,7 +9,6 @@ import ContentFilterPanel from '../panels/ContentFilterPanel'; import NestFeederPanel from '../panels/NestFeederPanel'; import OllamaPanel from '../panels/OllamaPanel'; import WalletPanel from '../panels/WalletPanel'; -import XNostrPanel from '../panels/XNostrPanel'; import QueryCachePanel from '../panels/QueryCachePanel'; import useGenericSettings from '@app/hooks/useGenericSettings'; @@ -157,10 +156,6 @@ const AdvancedSettingsLayout: React.FC = ({ - - - - diff --git a/src/components/settings/panels/XNostrPanel.tsx b/src/components/settings/panels/XNostrPanel.tsx deleted file mode 100644 index 5298410c..00000000 --- a/src/components/settings/panels/XNostrPanel.tsx +++ /dev/null @@ -1,631 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Form, Input, InputNumber, Switch, Tooltip, Button, Space, Divider } from 'antd'; -import { SaveOutlined } from '@ant-design/icons'; -import { - QuestionCircleOutlined, - PlusOutlined, - DeleteOutlined, - TwitterOutlined, - FolderOutlined, - ClockCircleOutlined, - TeamOutlined -} from '@ant-design/icons'; -import useGenericSettings from '@app/hooks/useGenericSettings'; -import { SettingsGroupType, XNostrNitterInstance } from '@app/types/settings.types'; -import BaseSettingsPanel from '../BaseSettingsPanel'; -import styled from 'styled-components'; - -const NitterInstanceContainer = styled.div` - margin-bottom: 16px; - padding: 16px; - border: 1px solid #f0f0f0; - border-radius: 4px; - background-color: rgba(0, 0, 0, 0.1); -`; - -const XNostrPanel: React.FC = () => { - const { - settings, - loading, - error, - updateSettings, - saveSettings: saveXNostrSettings, - } = useGenericSettings('xnostr'); - - const [form] = Form.useForm(); - const [isUserEditing, setIsUserEditing] = useState(false); - const [nitterInstances, setNitterInstances] = useState([]); - - // Listen for save button click - useEffect(() => { - const handleGlobalSave = () => { - setTimeout(() => { - setIsUserEditing(false); - }, 200); - }; - - document.addEventListener('settings-saved', handleGlobalSave); - - return () => { - document.removeEventListener('settings-saved', handleGlobalSave); - }; - }, []); - - // Update form values when settings change, but only if user isn't actively editing - useEffect(() => { - if (settings && !isUserEditing) { - console.log('XNostrPanel - Received settings:', settings); - - // Transform property names to match form field names - // The API returns properties without the prefix, but the form expects prefixed names - const settingsObj = settings as Record; - - // Create a transformed settings object with prefixed property names - const formValues = { - xnostr_enabled: settingsObj.enabled, - xnostr_browser_path: settingsObj.browser_path, - xnostr_browser_pool_size: typeof settingsObj.browser_pool_size === 'string' - ? parseInt(settingsObj.browser_pool_size) - : settingsObj.browser_pool_size, - xnostr_check_interval: typeof settingsObj.check_interval === 'string' - ? parseInt(settingsObj.check_interval) - : settingsObj.check_interval, - xnostr_concurrency: typeof settingsObj.concurrency === 'string' - ? parseInt(settingsObj.concurrency) - : settingsObj.concurrency, - xnostr_temp_dir: settingsObj.temp_dir, - xnostr_update_interval: typeof settingsObj.update_interval === 'string' - ? parseInt(settingsObj.update_interval) - : settingsObj.update_interval, - // Handle nested objects - verification intervals - xnostr_verification_intervals_follower_update_interval_days: - settingsObj.verification_intervals?.follower_update_interval_days || 7, - xnostr_verification_intervals_full_verification_interval_days: - settingsObj.verification_intervals?.full_verification_interval_days || 30, - xnostr_verification_intervals_max_verification_attempts: - settingsObj.verification_intervals?.max_verification_attempts || 5, - // Handle nested objects - nitter settings - xnostr_nitter_failure_threshold: - settingsObj.nitter?.failure_threshold || 3, - xnostr_nitter_recovery_threshold: - settingsObj.nitter?.recovery_threshold || 2, - xnostr_nitter_requests_per_minute: - settingsObj.nitter?.requests_per_minute || 10, - }; - - console.log('XNostrPanel - Transformed form values:', formValues); - - // Set form values with a slight delay to ensure the form is ready - setTimeout(() => { - form.setFieldsValue(formValues); - console.log('XNostrPanel - Form values after set:', form.getFieldsValue()); - }, 100); - - // Set nitter instances - if (settingsObj.nitter?.instances) { - setNitterInstances(settingsObj.nitter.instances); - } else { - setNitterInstances([]); - } - } - }, [settings, form, isUserEditing]); - - // Handle form value changes - const handleValuesChange = (changedValues: Partial>) => { - setIsUserEditing(true); // Mark that user is currently editing - console.log('XNostrPanel - changedValues:', changedValues); - console.log('XNostrPanel - current form values:', form.getFieldsValue()); - - // Create a partial settings object from the changed values - const updatedSettings: Partial> = {}; - - // Handle simple fields - if ('xnostr_enabled' in changedValues) { - updatedSettings.xnostr_enabled = changedValues.xnostr_enabled; - } - if ('xnostr_browser_path' in changedValues) { - updatedSettings.xnostr_browser_path = changedValues.xnostr_browser_path; - } - if ('xnostr_browser_pool_size' in changedValues) { - updatedSettings.xnostr_browser_pool_size = changedValues.xnostr_browser_pool_size; - } - if ('xnostr_check_interval' in changedValues) { - updatedSettings.xnostr_check_interval = changedValues.xnostr_check_interval; - } - if ('xnostr_concurrency' in changedValues) { - updatedSettings.xnostr_concurrency = changedValues.xnostr_concurrency; - } - if ('xnostr_temp_dir' in changedValues) { - updatedSettings.xnostr_temp_dir = changedValues.xnostr_temp_dir; - } - if ('xnostr_update_interval' in changedValues) { - updatedSettings.xnostr_update_interval = changedValues.xnostr_update_interval; - } - - // Handle nested verification intervals object - if ( - 'xnostr_verification_intervals_follower_update_interval_days' in changedValues || - 'xnostr_verification_intervals_full_verification_interval_days' in changedValues || - 'xnostr_verification_intervals_max_verification_attempts' in changedValues - ) { - // Get current form values for verification intervals - const formValues = form.getFieldsValue(); - updatedSettings.xnostr_verification_intervals = { - follower_update_interval_days: formValues.xnostr_verification_intervals_follower_update_interval_days, - full_verification_interval_days: formValues.xnostr_verification_intervals_full_verification_interval_days, - max_verification_attempts: formValues.xnostr_verification_intervals_max_verification_attempts - }; - } - - // Handle nested nitter settings object - if ( - 'xnostr_nitter_failure_threshold' in changedValues || - 'xnostr_nitter_recovery_threshold' in changedValues || - 'xnostr_nitter_requests_per_minute' in changedValues - ) { - // Get current form values for nitter settings - const formValues = form.getFieldsValue(); - - // We need to preserve the current instances when updating other nitter settings - const currentInstances = settings?.xnostr_nitter?.instances || nitterInstances; - - updatedSettings.xnostr_nitter = { - failure_threshold: formValues.xnostr_nitter_failure_threshold, - recovery_threshold: formValues.xnostr_nitter_recovery_threshold, - requests_per_minute: formValues.xnostr_nitter_requests_per_minute, - instances: currentInstances - }; - } - - // Only update if we have changes - if (Object.keys(updatedSettings).length > 0) { - updateSettings(updatedSettings); - } - }; - - // Add a new nitter instance - const handleAddNitterInstance = () => { - const newInstance: XNostrNitterInstance = { - priority: nitterInstances.length + 1, - url: '' - }; - - const newInstances = [...nitterInstances, newInstance]; - setNitterInstances(newInstances); - setIsUserEditing(true); - - // Update settings with new instances - const updatedSettings: Partial> = settings ? { ...settings } : {}; - // Initialize xnostr_nitter if needed - if (!updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter = { - failure_threshold: form.getFieldValue('xnostr_nitter_failure_threshold') || 3, - recovery_threshold: form.getFieldValue('xnostr_nitter_recovery_threshold') || 2, - requests_per_minute: form.getFieldValue('xnostr_nitter_requests_per_minute') || 10, - instances: [] - }; - } - // Ensure xnostr_nitter is defined before setting instances - if (updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter.instances = newInstances; - } - updateSettings(updatedSettings); - }; - - // Remove a nitter instance - const handleRemoveNitterInstance = (index: number) => { - const newInstances = [...nitterInstances]; - newInstances.splice(index, 1); - - // Update priorities - newInstances.forEach((instance, idx) => { - instance.priority = idx + 1; - }); - - setNitterInstances(newInstances); - setIsUserEditing(true); - - // Update settings with new instances - const updatedSettings: Partial> = settings ? { ...settings } : {}; - if (updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter.instances = newInstances; - updateSettings(updatedSettings); - } - }; - - // Update a nitter instance - const handleUpdateNitterInstance = (index: number, field: keyof XNostrNitterInstance, value: number | string | null) => { - const newInstances = [...nitterInstances]; - - // Handle null values from InputNumber - if (value === null && field === 'priority') { - value = 0; // Default to 0 for null number values - } - - // Use a more specific type assertion based on the field - if (field === 'priority') { - newInstances[index].priority = value as number; - } else if (field === 'url') { - newInstances[index].url = value as string; - } - - setNitterInstances(newInstances); - setIsUserEditing(true); - - // Update settings with new instances - const updatedSettings: Partial> = settings ? { ...settings } : {}; - if (updatedSettings.xnostr_nitter) { - updatedSettings.xnostr_nitter.instances = newInstances; - updateSettings(updatedSettings); - } - }; - - const handlePanelSave = async () => { - try { - await saveXNostrSettings(); - setIsUserEditing(false); - console.log('XNostr settings saved successfully'); - } catch (error) { - console.error('Error saving XNostr settings:', error); - } - }; - - return ( - } - onClick={handlePanelSave} - disabled={loading} - > - Save - - } - > -
{ - console.log('Form submitted with values:', values); - setIsUserEditing(false); - }} - > - {/* General XNostr Settings */} - - Enable XNostr  - - - - - } - valuePropName="checked" - > - - - - - Browser Path  - - - - - } - > - } - placeholder="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" - /> - - - - Browser Pool Size  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Temporary Directory  - - - - - } - > - } - placeholder="/tmp/xnostr-verification" - /> - - - - Check Interval (seconds)  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - } - min={1} - style={{ width: '100%' }} - /> - - - - Concurrency  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - } - min={1} - style={{ width: '100%' }} - /> - - - - Update Interval (hours)  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - } - min={1} - style={{ width: '100%' }} - /> - - - Nitter Settings - - {/* Nitter Settings */} - - Failure Threshold  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Recovery Threshold  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Requests Per Minute  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Nitter Instances  - - - - - } - > - {nitterInstances.map((instance, index) => ( - - - - handleUpdateNitterInstance(index, 'priority', value)} - min={1} - style={{ width: '100%' }} - /> - - - - handleUpdateNitterInstance(index, 'url', e.target.value)} - placeholder="https://nitter.net/" - prefix={} - /> - - - - - - ))} - - - - - Verification Intervals - - {/* Verification Interval Settings */} - - Follower Update Interval (days)  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Full Verification Interval (days)  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - - Max Verification Attempts  - - - - - } - rules={[ - { type: 'number', min: 1, message: 'Value must be at least 1' } - ]} - > - - - - -

- Note: XNostr is used for Twitter verification of Nostr profiles. It requires a browser to be installed and accessible. - The Nitter instances are used to scrape Twitter profiles when the Twitter API is not available. -

-
-
-
- ); -}; - -export default XNostrPanel; diff --git a/src/types/settings.types.ts b/src/types/settings.types.ts index 8b9778e6..9cb404cc 100644 --- a/src/types/settings.types.ts +++ b/src/types/settings.types.ts @@ -95,7 +95,6 @@ export type SettingsGroupName = | 'content_filter' | 'nest_feeder' | 'ollama' - | 'xnostr' | 'relay_info' | 'wallet' | 'general' @@ -107,7 +106,6 @@ export type SettingsGroupType = T extends 'content_filter' ? ContentFilterSettings : T extends 'nest_feeder' ? NestFeederSettings : T extends 'ollama' ? OllamaSettings : - T extends 'xnostr' ? XNostrSettings : T extends 'relay_info' ? RelayInfoSettings : T extends 'wallet' ? WalletSettings : T extends 'general' ? GeneralSettings :