Compare commits
8 Commits
fix/thinki
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
038da0de63 | ||
|
|
8924f954dd | ||
|
|
06b108c40d | ||
|
|
b1e63470a5 | ||
|
|
ea9e7fccda | ||
|
|
97ab200657 | ||
|
|
7a49042d7f | ||
|
|
33983c26f4 |
@@ -33,6 +33,7 @@ class BackupManager {
|
||||
accessKeyId: string
|
||||
secretAccessKey: string
|
||||
root?: string
|
||||
bypassProxy?: boolean
|
||||
} | null = null
|
||||
|
||||
private cachedWebdavConnectionConfig: {
|
||||
@@ -120,7 +121,8 @@ class BackupManager {
|
||||
cachedConfig.bucket === config.bucket &&
|
||||
cachedConfig.accessKeyId === config.accessKeyId &&
|
||||
cachedConfig.secretAccessKey === config.secretAccessKey &&
|
||||
cachedConfig.root === config.root
|
||||
cachedConfig.root === config.root &&
|
||||
cachedConfig.bypassProxy === config.bypassProxy
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,6 +149,11 @@ class BackupManager {
|
||||
const configChanged = !this.isS3ConfigEqual(this.cachedS3ConnectionConfig, config)
|
||||
|
||||
if (configChanged || !this.s3Storage) {
|
||||
// Destroy old instance to clean up bypass rules
|
||||
if (this.s3Storage) {
|
||||
this.s3Storage.destroy()
|
||||
}
|
||||
|
||||
this.s3Storage = new S3Storage(config)
|
||||
// 只缓存连接相关的配置字段
|
||||
this.cachedS3ConnectionConfig = {
|
||||
@@ -155,7 +162,8 @@ class BackupManager {
|
||||
bucket: config.bucket,
|
||||
accessKeyId: config.accessKeyId,
|
||||
secretAccessKey: config.secretAccessKey,
|
||||
root: config.root
|
||||
root: config.root,
|
||||
bypassProxy: config.bypassProxy
|
||||
}
|
||||
logger.debug('[BackupManager] Created new S3Storage instance')
|
||||
} else {
|
||||
|
||||
@@ -12,6 +12,8 @@ import { Dispatcher, EnvHttpProxyAgent, getGlobalDispatcher, setGlobalDispatcher
|
||||
|
||||
const logger = loggerService.withContext('ProxyManager')
|
||||
let byPassRules: string[] = []
|
||||
// Dynamic bypass rules that can be added/removed at runtime (e.g., for S3 endpoints)
|
||||
const dynamicBypassRules: string[] = []
|
||||
|
||||
type HostnameMatchType = 'exact' | 'wildcardSubdomain' | 'generalWildcard'
|
||||
|
||||
@@ -222,7 +224,10 @@ export const updateByPassRules = (rules: string[]): void => {
|
||||
byPassRules = rules
|
||||
parsedByPassRules = []
|
||||
|
||||
for (const rule of rules) {
|
||||
// Combine static bypass rules with dynamic ones
|
||||
const allRules = [...rules, ...dynamicBypassRules]
|
||||
|
||||
for (const rule of allRules) {
|
||||
const parsedRule = parseProxyBypassRule(rule)
|
||||
if (parsedRule) {
|
||||
parsedByPassRules.push(parsedRule)
|
||||
@@ -232,6 +237,33 @@ export const updateByPassRules = (rules: string[]): void => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a dynamic bypass rule at runtime (e.g., for S3 endpoints)
|
||||
* @param rule - The bypass rule to add (e.g., hostname or domain pattern)
|
||||
*/
|
||||
export const addDynamicBypassRule = (rule: string): void => {
|
||||
if (!dynamicBypassRules.includes(rule)) {
|
||||
dynamicBypassRules.push(rule)
|
||||
// Re-parse all rules with the new dynamic rule
|
||||
updateByPassRules(byPassRules)
|
||||
logger.info(`Added dynamic bypass rule: ${rule}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a dynamic bypass rule
|
||||
* @param rule - The bypass rule to remove
|
||||
*/
|
||||
export const removeDynamicBypassRule = (rule: string): void => {
|
||||
const index = dynamicBypassRules.indexOf(rule)
|
||||
if (index !== -1) {
|
||||
dynamicBypassRules.splice(index, 1)
|
||||
// Re-parse all rules without the removed dynamic rule
|
||||
updateByPassRules(byPassRules)
|
||||
logger.info(`Removed dynamic bypass rule: ${rule}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const isByPass = (url: string) => {
|
||||
if (parsedByPassRules.length === 0) {
|
||||
return false
|
||||
@@ -586,6 +618,22 @@ export class ProxyManager {
|
||||
// set proxy for electron
|
||||
app.setProxy(config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a dynamic bypass rule for a specific endpoint
|
||||
* @param rule - The bypass rule to add (e.g., hostname or domain pattern)
|
||||
*/
|
||||
addDynamicBypassRule(rule: string): void {
|
||||
addDynamicBypassRule(rule)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a dynamic bypass rule
|
||||
* @param rule - The bypass rule to remove
|
||||
*/
|
||||
removeDynamicBypassRule(rule: string): void {
|
||||
removeDynamicBypassRule(rule)
|
||||
}
|
||||
}
|
||||
|
||||
export const proxyManager = new ProxyManager()
|
||||
|
||||
@@ -11,6 +11,8 @@ import type { S3Config } from '@types'
|
||||
import * as net from 'net'
|
||||
import { Readable } from 'stream'
|
||||
|
||||
import { proxyManager } from './ProxyManager'
|
||||
|
||||
const logger = loggerService.withContext('S3Storage')
|
||||
|
||||
/**
|
||||
@@ -35,9 +37,12 @@ export default class S3Storage {
|
||||
private client: S3Client
|
||||
private bucket: string
|
||||
private root: string
|
||||
private endpoint: string
|
||||
|
||||
constructor(config: S3Config) {
|
||||
const { endpoint, region, accessKeyId, secretAccessKey, bucket, root } = config
|
||||
const { endpoint, region, accessKeyId, secretAccessKey, bucket, root, bypassProxy = true } = config
|
||||
|
||||
this.endpoint = endpoint
|
||||
|
||||
const usePathStyle = (() => {
|
||||
if (!endpoint) return false
|
||||
@@ -57,6 +62,22 @@ export default class S3Storage {
|
||||
}
|
||||
})()
|
||||
|
||||
// Use ProxyManager's dynamic bypass rules instead of custom dispatcher
|
||||
// When bypassProxy is true (default), add the S3 endpoint to proxy bypass rules
|
||||
// to avoid proxy interference with large file uploads that can cause incomplete transfers
|
||||
// Error example: "Io error: put_object write size < data.size(), w_size=15728640, data.size=16396159"
|
||||
if (bypassProxy && endpoint) {
|
||||
try {
|
||||
const url = new URL(endpoint)
|
||||
const hostname = url.hostname
|
||||
// Add the hostname to dynamic bypass rules
|
||||
proxyManager.addDynamicBypassRule(hostname)
|
||||
logger.debug(`[S3Storage] Added S3 endpoint to bypass rules: ${hostname}`)
|
||||
} catch (e) {
|
||||
logger.warn(`[S3Storage] Failed to add endpoint to bypass rules: ${endpoint}`, e as Error)
|
||||
}
|
||||
}
|
||||
|
||||
this.client = new S3Client({
|
||||
region,
|
||||
endpoint: endpoint || undefined,
|
||||
@@ -77,6 +98,22 @@ export default class S3Storage {
|
||||
this.checkConnection = this.checkConnection.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up resources and remove bypass rules
|
||||
*/
|
||||
destroy(): void {
|
||||
if (this.endpoint) {
|
||||
try {
|
||||
const url = new URL(this.endpoint)
|
||||
const hostname = url.hostname
|
||||
proxyManager.removeDynamicBypassRule(hostname)
|
||||
logger.debug(`[S3Storage] Removed S3 endpoint from bypass rules: ${hostname}`)
|
||||
} catch (e) {
|
||||
logger.warn(`[S3Storage] Failed to remove endpoint from bypass rules: ${this.endpoint}`, e as Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部辅助方法,用来拼接带 root 的对象 key
|
||||
*/
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, e.g: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "When enabled, S3 requests bypass the application proxy to prevent data corruption during large file uploads. Recommended to keep enabled unless your S3 endpoint requires proxy access.",
|
||||
"label": "Bypass Proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API Endpoint",
|
||||
"placeholder": "https://s3.example.com"
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "存储桶",
|
||||
"placeholder": "Bucket, 例如: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "开启后,S3 请求将绕过应用程序代理,以防止大文件上传时的数据损坏。建议保持开启,除非您的 S3 端点需要通过代理访问。",
|
||||
"label": "绕过代理"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API 地址",
|
||||
"placeholder": "https://s3.example.com"
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "儲存桶",
|
||||
"placeholder": "Bucket,例如: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "開啟後,S3 請求將繞過應用程式代理,以防止大檔案上傳時的資料損壞。建議保持開啟,除非您的 S3 端點需要透過代理存取。",
|
||||
"label": "繞過代理"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API 位址",
|
||||
"placeholder": "https://s3.example.com"
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, z. B.: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Wenn aktiviert, umgehen S3-Anfragen den Anwendungs-Proxy, um Datenbeschädigung beim Hochladen großer Dateien zu verhindern. Es wird empfohlen, diese Option aktiviert zu lassen, es sei denn, Ihr S3-Endpunkt erfordert Proxy-Zugriff.",
|
||||
"label": "Proxy umgehen"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API-Adresse",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS-Zugriffsschlüssel-ID",
|
||||
"access_key_id_help": "Ihre AWS-Zugriffsschlüssel-ID, um auf AWS Bedrock-Dienste zuzugreifen",
|
||||
"api_key": "Bedrock-API-Schlüssel",
|
||||
"api_key_help": "Ihr AWS-Bedrock-API-Schlüssel für die Authentifizierung",
|
||||
"auth_type": "Authentifizierungstyp",
|
||||
"auth_type_api_key": "Bedrock-API-Schlüssel",
|
||||
"auth_type_help": "Wähle zwischen IAM-Anmeldeinformationen oder Bedrock-API-Schlüssel-Authentifizierung",
|
||||
"auth_type_iam": "IAM-Anmeldeinformationen",
|
||||
"description": "AWS Bedrock ist ein vollständig verwalteter Basismodell-Dienst von Amazon, der eine Vielzahl moderner großer Sprachmodelle unterstützt",
|
||||
"region": "AWS-Region",
|
||||
"region_help": "Ihre AWS-Serviceregion, z.B. us-east-1",
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Δοχείο",
|
||||
"placeholder": "Bucket, π.χ.: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Όταν είναι ενεργοποιημένο, τα αιτήματα S3 παρακάμπτουν τον διαμεσολαβητή εφαρμογής για να αποτρέψουν τη διαφθορά δεδομένων κατά τη μεταφόρτωση μεγάλων αρχείων. Συνιστάται να παραμένει ενεργοποιημένο, εκτός εάν το τελικό σημείο S3 απαιτεί πρόσβαση μέσω διαμεσολαβητή.",
|
||||
"label": "Παράκαμψη διαμεσολαβητή"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Διεύθυνση API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "Αναγνωριστικό κλειδιού πρόσβασης AWS",
|
||||
"access_key_id_help": "Το ID του κλειδιού πρόσβασης AWS που χρησιμοποιείται για την πρόσβαση στην υπηρεσία AWS Bedrock",
|
||||
"api_key": "Κλειδί API Bedrock",
|
||||
"api_key_help": "Το κλειδί API του AWS Bedrock για έλεγχο ταυτότητας",
|
||||
"auth_type": "Τύπος Πιστοποίησης",
|
||||
"auth_type_api_key": "Κλειδί API Bedrock",
|
||||
"auth_type_help": "Επιλέξτε μεταξύ πιστοποιητικών IAM ή πιστοποίησης με κλειδί API Bedrock",
|
||||
"auth_type_iam": "Διαπιστευτήρια IAM",
|
||||
"description": "Η AWS Bedrock είναι μια πλήρως διαχειριζόμενη υπηρεσία βασικών μοντέλων που παρέχεται από την Amazon και υποστηρίζει διάφορα προηγμένα μεγάλα γλωσσικά μοντέλα.",
|
||||
"region": "Περιοχές AWS",
|
||||
"region_help": "Η περιοχή υπηρεσίας AWS σας, για παράδειγμα us-east-1",
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, por ejemplo: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Cuando está habilitado, las solicitudes a S3 omiten el proxy de la aplicación para evitar la corrupción de datos durante las cargas de archivos grandes. Se recomienda mantenerlo habilitado a menos que tu punto de enlace de S3 requiera acceso al proxy.",
|
||||
"label": "Omitir Proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Dirección API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "ID de clave de acceso de AWS",
|
||||
"access_key_id_help": "Su ID de clave de acceso de AWS, utilizado para acceder al servicio AWS Bedrock",
|
||||
"api_key": "Clave de API de Bedrock",
|
||||
"api_key_help": "Tu clave de API de AWS Bedrock para la autenticación",
|
||||
"auth_type": "Tipo de autenticación",
|
||||
"auth_type_api_key": "Clave de API de Bedrock",
|
||||
"auth_type_help": "Elige entre credenciales IAM o autenticación con clave API de Bedrock",
|
||||
"auth_type_iam": "Credenciales IAM",
|
||||
"description": "AWS Bedrock es un servicio de modelos fundamentales completamente gestionado proporcionado por Amazon, que admite diversos modelos avanzados de lenguaje de gran tamaño.",
|
||||
"region": "Región de AWS",
|
||||
"region_help": "Su región de servicio AWS, por ejemplo us-east-1",
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, par exemple : example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Lorsqu’il est activé, les requêtes S3 contournent le proxy de l’application pour éviter la corruption des données lors du téléversement de gros fichiers. Il est recommandé de le laisser activé sauf si votre point de terminaison S3 nécessite un accès par proxy.",
|
||||
"label": "Contourner le proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Adresse API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "Identifiant de clé d'accès AWS",
|
||||
"access_key_id_help": "Votre identifiant de clé d'accès AWS, utilisé pour accéder au service AWS Bedrock",
|
||||
"api_key": "Clé API Bedrock",
|
||||
"api_key_help": "Votre clé API AWS Bedrock pour l'authentification",
|
||||
"auth_type": "Type d'authentification",
|
||||
"auth_type_api_key": "Clé API Bedrock",
|
||||
"auth_type_help": "Choisissez entre l'authentification par identifiants IAM ou par clé API Bedrock",
|
||||
"auth_type_iam": "Identifiants IAM",
|
||||
"description": "AWS Bedrock est un service de modèles de base entièrement géré proposé par Amazon, prenant en charge divers grands modèles linguistiques avancés.",
|
||||
"region": "Région AWS",
|
||||
"region_help": "Votre région de service AWS, par exemple us-east-1",
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "バケット",
|
||||
"placeholder": "Bucket、例: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "有効にすると、S3リクエストはアプリケーションプロキシをバイパスし、大容量ファイルのアップロード中のデータ破損を防ぎます。S3エンドポイントがプロキシアクセスを必要としない限り、有効のままにすることを推奨します。",
|
||||
"label": "プロキシをバイパス"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "APIエンドポイント",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS アクセスキー ID",
|
||||
"access_key_id_help": "あなたの AWS アクセスキー ID は、AWS Bedrock サービスへのアクセスに使用されます",
|
||||
"api_key": "Bedrock APIキー",
|
||||
"api_key_help": "認証用のAWS Bedrock APIキー",
|
||||
"auth_type": "認証タイプ",
|
||||
"auth_type_api_key": "Bedrock APIキー",
|
||||
"auth_type_help": "IAM認証情報とBedrock APIキー認証のどちらかを選択してください",
|
||||
"auth_type_iam": "IAM認証情報",
|
||||
"description": "AWS Bedrock は、Amazon が提供する完全に管理されたベースモデルサービスで、さまざまな最先端の大言語モデルをサポートしています",
|
||||
"region": "AWS リージョン",
|
||||
"region_help": "あなたの AWS サービスリージョン、例:us-east-1",
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, por exemplo: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Quando ativado, as solicitações S3 ignoram o proxy da aplicação para evitar corrupção de dados durante uploads de arquivos grandes. Recomenda-se manter ativado, a menos que seu endpoint S3 exija acesso por proxy.",
|
||||
"label": "Ignorar Proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Endereço da API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "ID da chave de acesso da AWS",
|
||||
"access_key_id_help": "O seu ID da chave de acesso AWS, utilizado para aceder ao serviço AWS Bedrock",
|
||||
"api_key": "Chave de API do Bedrock",
|
||||
"api_key_help": "Sua Chave de API AWS Bedrock para autenticação",
|
||||
"auth_type": "Tipo de Autenticação",
|
||||
"auth_type_api_key": "Chave de API do Bedrock",
|
||||
"auth_type_help": "Escolha entre credenciais IAM ou autenticação por chave de API do Bedrock",
|
||||
"auth_type_iam": "Credenciais IAM",
|
||||
"description": "A AWS Bedrock é um serviço de modelos fundamentais totalmente gerido fornecido pela Amazon, que suporta diversos modelos avançados de linguagem.",
|
||||
"region": "Região da AWS",
|
||||
"region_help": "A sua região de serviço da AWS, por exemplo, us-east-1",
|
||||
|
||||
@@ -3336,6 +3336,10 @@
|
||||
"label": "Корзина",
|
||||
"placeholder": "Корзина, например: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "При включении запросы к S3 обходят прокси-приложение, чтобы предотвратить повреждение данных при загрузке больших файлов. Рекомендуется оставить включённым, если только ваш S3-эндпоинт не требует доступа через прокси.",
|
||||
"label": "Обход прокси"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Конечная точка API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4260,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS Ключ доступа ID",
|
||||
"access_key_id_help": "Ваш AWS Ключ доступа ID для доступа к AWS Bedrock",
|
||||
"api_key": "Ключ API Bedrock",
|
||||
"api_key_help": "Ваш API-ключ AWS Bedrock для аутентификации",
|
||||
"auth_type": "Тип аутентификации",
|
||||
"auth_type_api_key": "Ключ API Bedrock",
|
||||
"auth_type_help": "Выберите между аутентификацией с помощью учетных данных IAM или ключа API Bedrock",
|
||||
"auth_type_iam": "Учетные данные IAM",
|
||||
"description": "AWS Bedrock — это полное управляемое сервисное предложение для моделей, поддерживающее различные современные модели языка",
|
||||
"region": "AWS регион",
|
||||
"region_help": "Ваш регион AWS, например us-east-1",
|
||||
|
||||
@@ -31,7 +31,8 @@ const S3Settings: FC = () => {
|
||||
root: s3RootInit = '',
|
||||
syncInterval: s3SyncIntervalInit = 0,
|
||||
maxBackups: s3MaxBackupsInit = 5,
|
||||
skipBackupFile: s3SkipBackupFileInit = false
|
||||
skipBackupFile: s3SkipBackupFileInit = false,
|
||||
bypassProxy: s3BypassProxyInit = true
|
||||
} = s3
|
||||
|
||||
const [endpoint, setEndpoint] = useState<string | undefined>(s3EndpointInit)
|
||||
@@ -41,6 +42,7 @@ const S3Settings: FC = () => {
|
||||
const [secretAccessKey, setSecretAccessKey] = useState<string | undefined>(s3SecretAccessKeyInit)
|
||||
const [root, setRoot] = useState<string | undefined>(s3RootInit)
|
||||
const [skipBackupFile, setSkipBackupFile] = useState<boolean>(s3SkipBackupFileInit)
|
||||
const [bypassProxy, setBypassProxy] = useState<boolean>(s3BypassProxyInit)
|
||||
const [backupManagerVisible, setBackupManagerVisible] = useState(false)
|
||||
|
||||
const [syncInterval, setSyncInterval] = useState<number>(s3SyncIntervalInit)
|
||||
@@ -82,6 +84,11 @@ const S3Settings: FC = () => {
|
||||
dispatch(setS3Partial({ skipBackupFile: value }))
|
||||
}
|
||||
|
||||
const onBypassProxyChange = (value: boolean) => {
|
||||
setBypassProxy(value)
|
||||
dispatch(setS3Partial({ bypassProxy: value }))
|
||||
}
|
||||
|
||||
const renderSyncStatus = () => {
|
||||
if (!endpoint) return null
|
||||
|
||||
@@ -261,6 +268,14 @@ const S3Settings: FC = () => {
|
||||
<SettingRow>
|
||||
<SettingHelpText>{t('settings.data.s3.skipBackupFile.help')}</SettingHelpText>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.data.s3.bypassProxy.label')}</SettingRowTitle>
|
||||
<Switch checked={bypassProxy} onChange={onBypassProxyChange} />
|
||||
</SettingRow>
|
||||
<SettingRow>
|
||||
<SettingHelpText>{t('settings.data.s3.bypassProxy.help')}</SettingHelpText>
|
||||
</SettingRow>
|
||||
{syncInterval > 0 && (
|
||||
<>
|
||||
<SettingDivider />
|
||||
|
||||
@@ -401,7 +401,8 @@ export const initialState: SettingsState = {
|
||||
autoSync: false,
|
||||
syncInterval: 0,
|
||||
maxBackups: 0,
|
||||
skipBackupFile: false
|
||||
skipBackupFile: false,
|
||||
bypassProxy: true
|
||||
},
|
||||
|
||||
// Developer mode
|
||||
|
||||
@@ -883,6 +883,7 @@ export type S3Config = {
|
||||
autoSync: boolean
|
||||
syncInterval: number
|
||||
maxBackups: number
|
||||
bypassProxy?: boolean // Whether to bypass proxy for S3 requests (default: true)
|
||||
}
|
||||
|
||||
export type { Message } from './newMessage'
|
||||
|
||||
Reference in New Issue
Block a user