🎨 Support local file system sync & backup (#13663)

* 🎨 Use local file system sync & backup

* ⬆️ dejavu

* 🎨 Add the settings panel of local file system sync & backup

* 📝 Update user guides of local file system sync & backup

* 🎨 Adjust supported runtime environments
This commit is contained in:
Yingyi / 颖逸 2024-12-31 21:06:13 +08:00 committed by GitHub
parent 0386bc9ebd
commit 6ee4705e2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 408 additions and 32 deletions

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "نظام الملفات المحلي",
"deviceNotSupport": "الجهاز الحالي غير مدعوم",
"second": "ثانية",
"syncInterval": "الفاصل الزمني للمزامنة",
"syncIntervalTip": "مزامنة البيانات تلقائياً بعد أن توقف عن التغيير",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "‫المحدد حاليا هو خدمة تخزين السحابة التي توفرها رسميا SiYuan، والتي تدعم فقط المستخدمين المشتركين المدفوعة‬",
"syncThirdPartyProviderS3Intro": "‫المحدد حاليا هو خدمة تخزين سحابية تابعة لطرف ثالث متوافقة مع بروتوكول Amazon S3 (على سبيل المثال <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>، <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>، <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "‫المحدد حاليا هو خدمة تخزين سحابية لطرف ثالث مع بروتوكول WebDAV. بسبب ضعف أداء هذا البروتوكول وعدم كفاية استقراره، يوصى باختيار خدمة S3 أولا‬",
"syncThirdPartyProviderLocalIntro": "‫المحدد حاليا هو خدمة تخزين سحابية لطرف ثالث مع بروتوكوليتم حاليًا اختيار خدمة التخزين التي يوفرها نظام الملفات المحلي. الرجاء إدخال المسار الكامل للمجلد المحلي في حقل <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "‫قبل استخدام هذه الميزة، يرجى الانتباه إلى القيود التقنية وبنود الفوترة لخدمة التخزين السحابي من الطرف الثالث: <div class=\\\"b3-label__text\\\"><ul class='fn__list'><li>القيود التقنية مثل تكرار استدعاء الواجهة وعرض النطاق الترددي</li><li>بنود الفوترة مثل مساحة التخزين وحركة المرور</li><li>شروط الاستخدام وضمان التوفر</li></ul></div><div class='fn__hr'></div>إخلاء المسؤولية: للمزيد من التفاصيل، يرجى الرجوع إلى الشروط ذات الصلة في ترخيص المصدر المفتوح AGPLv3 المستخدم في SiYuan",
"syncProvider": "موفر خدمات التخزين السحابي",
"syncProviderTip": "إذا تم اختياره، سيتم استخدام خدمة التخزين السحابية لهذا الموفر لتحقيق مزامنة السحابة ووظائف النسخ الاحتياطي",
@ -1581,4 +1584,4 @@
"251": "‫مجموع الأصول غير المستخدمة [%d]، [%d] فقط منها مدرج هنا‬",
"252": "\uD83D\uDEA8 قد يقوم Microsoft Defender بحذف النواة عن طريق الخطأ، وحذف البيانات وتقليل الأداء بشكل كبير. يوصى بإضافة مسار التثبيت ومسار مساحة العمل الخاصة بـ SiYuan إلى قائمة الاستثناءات<span class=\"fn__space\"></span><button id=\"addMicrosoftDefenderExclusion\" class=\"b3-button b3-button--white\">إضافة</button><span class=\"fn__space\"></span>"
}
}
}

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "Lokales Dateisystem",
"deviceNotSupport": "Das aktuelle Gerät wird nicht unterstützt",
"second": "Sekunde",
"syncInterval": "Synchronisierungsintervall",
"syncIntervalTip": "Automatische Datensynchronisierung, nachdem die Daten nicht mehr geändert werden",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "Derzeit ausgewählt ist der von SiYuan offiziell bereitgestellte Cloud-Speicherdienst, der nur abonnierte Benutzer unterstützt.",
"syncThirdPartyProviderS3Intro": "Derzeit ausgewählt ist ein Drittanbieter-Cloudspeicherdienst, der mit dem Amazon S3-Protokoll kompatibel ist (z. B. <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>, <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>, <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "Derzeit ausgewählt ist ein Drittanbieter-Cloudspeicherdienst mit dem WebDAV-Protokoll. Aufgrund der schlechten Leistung und unzureichenden Stabilität dieses Protokolls wird empfohlen, zuerst den S3-Dienst auszuwählen.",
"syncThirdPartyProviderLocalIntro": "Derzeit wird der vom lokalen Dateisystem bereitgestellte Speicherdienst ausgewählt. Bitte geben Sie im Feld <code class='fn__code'>Endpoint</code> den vollständigen Pfad des lokalen Ordners ein",
"syncThirdPartyProviderTip": "Bitte beachten Sie vor der Nutzung dieser Funktion die technischen Einschränkungen und Abrechnungspositionen des Drittanbieter-Cloudspeicherdienstes: <div class=\"b3-label__text\"><ul class='fn__list'><li>Technische Einschränkungen wie Schnittstellenaufruffrequenz und Bandbreite</li><li>Abrechnungspositionen wie Speicherplatz und Datenverkehr</li><li>Nutzungsbedingungen und Verfügbarkeitsgarantie</li></ul></div><div class='fn__hr'></div>Haftungsausschluss: Für Details konsultieren Sie bitte die entsprechenden Bestimmungen in der Open Source Lizenz AGPLv3, die von SiYuan verwendet wird.",
"syncProvider": "Cloud-Speicherdienstanbieter",
"syncProviderTip": "Wenn ausgewählt, wird der Cloud-Speicherdienst dieses Anbieters verwendet, um Cloud-Synchronisations- und Backup-Funktionen zu erreichen.",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "Local file system",
"deviceNotSupport": "The current device is not supported",
"second": "second",
"syncInterval": "sync interval",
"syncIntervalTip": "Automatically sync data after it stops changing",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "Currently selected is the cloud storage service officially provided by SiYuan, which only supports paid subscription users",
"syncThirdPartyProviderS3Intro": "The current selected is a third-party cloud storage service compatible with the Amazon S3 protocol (eg <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>, <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>, <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "The currently selected is a third-party cloud storage service with the WebDAV protocol. Due to the poor performance and insufficient stability of this protocol, it is recommended to choose the S3 service first",
"syncThirdPartyProviderLocalIntro": "The storage service provided by the local file system is currently selected. Please enter the full path of the local folder in the <code class='fn__code'>Endpoint</code> field",
"syncThirdPartyProviderTip": "Before using this feature, please pay attention to the technical limitations and billing items of the third-party cloud storage service: <div class=\"b3-label__text\"><ul class='fn__list'><li>Technical limitations such as interface calling frequency and bandwidth</li><li>Billing items such as storage space and traffic</li><li>Terms of use and availability guarantee</li></ul></div><div class='fn__hr'></div>Disclaimer: For details, please refer to the relevant terms in the open source license AGPLv3 used by SiYuan",
"syncProvider": "Cloud storage service provider",
"syncProviderTip": "If selected, the cloud storage service of this provider will be used to achieve cloud synchronization and backup functions",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "Sistema de archivos local",
"deviceNotSupport": "El dispositivo actual no es compatible",
"second": "segundo",
"syncInterval": "intervalo de sincronización",
"syncIntervalTip": "Sincronización automática de datos después de que los datos dejen de cambiar",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "Actualmente seleccionado es el servicio de almacenamiento en la nube proporcionado oficialmente por SiYuan, que solo admite usuarios de suscripción paga",
"syncThirdPartyProviderS3Intro": "El actual seleccionado es un servicio de almacenamiento en la nube de terceros compatible con el protocolo Amazon S3",
"syncThirdPartyProviderWebDAVIntro": "El servicio de almacenamiento en la nube de terceros del protocolo WebDAV está actualmente seleccionado. Debido al bajo rendimiento y la estabilidad insuficiente de este protocolo, se recomienda elegir primero el servicio S3",
"syncThirdPartyProviderLocalIntro": "Actualmente está seleccionado el servicio de almacenamiento proporcionado por el sistema de archivos local. Por favor, ingrese la ruta completa de la carpeta local en el campo <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "Antes de usar esta función, preste atención a las limitaciones técnicas y los elementos de facturación del servicio de almacenamiento en la nube de terceros: <div class=\"b3-label__text\"><ul class='fn__list'><li>Limitaciones técnicas, como la frecuencia de llamada de la interfaz y el ancho de banda</li><li >Artículos de facturación como espacio de almacenamiento y tráfico</li><li>Términos de uso y garantía de disponibilidad</li></ul></div><div class='fn__hr'></div>Descargo de responsabilidad: para obtener más información, consulte los términos relevantes en la licencia de código abierto AGPLv3 utilizado por SiYuan",
"syncProvider": "Proveedor de servicios de almacenamiento en la nube",
"syncProviderTip": "Si se selecciona, el servicio de almacenamiento en la nube de este proveedor se usará para lograr funciones de sincronización y copia de seguridad en la nube",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "Système de fichiers local",
"deviceNotSupport": "L'appareil actuel n'est pas pris en charge",
"second": "seconde",
"syncInterval": "intervalle de synchronisation",
"syncIntervalTip": "Synchronisation automatique des données après l'arrêt des modifications",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "Actuellement sélectionné est le service de stockage en nuage officiellement fourni par SiYuan, qui ne prend en charge que les utilisateurs d'abonnement payant",
"syncThirdPartyProviderS3Intro": "L'actuel sélectionné est un service de stockage cloud tiers compatible avec le protocole Amazon S3",
"syncThirdPartyProviderWebDAVIntro": "Le service de stockage cloud tiers du protocole WebDAV est actuellement sélectionné. En raison des performances médiocres et de la stabilité insuffisante de ce protocole, il est recommandé de choisir d'abord le service S3",
"syncThirdPartyProviderLocalIntro": "Le service de stockage fourni par le système de fichiers local est actuellement sélectionné. Veuillez saisir le chemin complet du dossier local dans le champ <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "Avant d'utiliser cette fonctionnalité, veuillez prêter attention aux limitations techniques et aux éléments de facturation du service de stockage cloud tiers : <div class=\"b3-label__text\"><ul class='fn__list'><li>Limitations techniques telles que la fréquence d'appel et la bande passante de l'interface</li><li >Éléments de facturation tels que l'espace de stockage et le trafic</li><li>Conditions d'utilisation et garantie de disponibilité</li></ul></div><div class='fn__hr'></div>Avis de non-responsabilité : pour plus de détails, veuillez vous référer aux termes pertinents dans la licence open source AGPLv3 utilisé par SiYuan",
"syncProvider": "Fournisseur de services de stockage en nuage",
"syncProviderTip": "Si sélectionné, le service de stockage cloud de ce fournisseur sera utilisé pour réaliser les fonctions de synchronisation et de sauvegarde cloud",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "מערכת קבצים מקומית",
"deviceNotSupport": "המכשיר הנוכחי אינו נתמך",
"second": "שנייה",
"syncInterval": "מרווח סנכרון",
"syncIntervalTip": "סנכרון נתונים אוטומטי לאחר שהנתונים מפסיקים להשתנות",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "נבחר עתה הוא שירות האחסון בענן המוצע רשמית על ידי SiYuan, אשר תומך רק במשתמשים בתשלום",
"syncThirdPartyProviderS3Intro": "הנבחר עתה הוא שירות אחסון בענן צד שלישי תואם עם פרוטוקול Amazon S3 (למשל <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>, <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>, <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "הנבחר עתה הוא שירות אחסון בענן צד שלישי עם פרוטוקול WebDAV. בשל ביצועים לקויים ויציבות בלתי מתאימה של פרוטוקול זה, הכרחי לבחור קודם בשירות S3",
"syncThirdPartyProviderLocalIntro": "שירות האחסון שסופק על ידי מערכת הקבצים המקומית נבחר כעת. אנא הזן את הנתיב המלא של התיקייה המקומית בשדה <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "לפני השימוש בתכונה זו, אנא שים לב למגבלות טכניות ופריטי חיוב של שירות האחסון בענן של צד שלישי: <div class=\"b3-label__text\"><ul class='fn__list'><li>מגבלות טכניות כמו תדירות קריאות ממשק ורוחב פס</li><li>פריטי חיוב כמו שטח אחסון ותעבורה</li><li>תנאי שימוש והתחייבות זמינות</li></ul></div><div class='fn__hr'></div>הבהרה: למידע נוסף, עיין בתנאים הרלוונטיים ברישיון הקוד הפתוח AGPLv3 בו משתמשת SiYuan",
"syncProvider": "ספק שירות אחסון בענן",
"syncProviderTip": "אם נבחר, שירות האחסון בענן של ספק זה ישמש כדי להשיג פונקציות סנכרון וגיבוי בענן",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "File system locale",
"deviceNotSupport": "Il dispositivo corrente non è supportato",
"second": "secondo",
"syncInterval": "intervallo di sincronizzazione",
"syncIntervalTip": "Sincronizzazione automatica dei dati dopo che non ci sono più variazioni",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "Attualmente è selezionato il servizio di archiviazione cloud ufficiale fornito da SiYuan, che supporta solo utenti abbonati a pagamento",
"syncThirdPartyProviderS3Intro": "Attualmente è selezionato un servizio di archiviazione cloud di terze parti compatibile con il protocollo Amazon S3 (es. <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>, <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>, <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "Attualmente è selezionato un servizio di archiviazione cloud di terze parti con protocollo WebDAV. A causa delle scarse prestazioni e della stabilità insufficiente di questo protocollo, si consiglia di scegliere prima il servizio S3",
"syncThirdPartyProviderLocalIntro": "Attualmente è selezionato il servizio di archiviazione fornito dal file system locale. Inserisci il percorso completo della cartella locale nel campo <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "Prima di utilizzare questa funzione, presta attenzione ai limiti tecnici e agli elementi di fatturazione del servizio di archiviazione cloud di terze parti: <div class=\"b3-label__text\"><ul class='fn__list'><li>Limitazioni tecniche come la frequenza delle chiamate dell'interfaccia e la larghezza di banda</li><li>Elementi di fatturazione come lo spazio di archiviazione e il traffico</li><li>Termini di utilizzo e garanzia di disponibilità</li></ul></div><div class='fn__hr'></div>Disclaimer: Per dettagli, si prega di consultare i termini pertinenti nella licenza open source AGPLv3 utilizzata da SiYuan",
"syncProvider": "Provider di servizio di archiviazione cloud",
"syncProviderTip": "Se selezionato, verrà utilizzato il servizio di archiviazione cloud di questo provider per sincronizzare e fare il backup dei dati",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "ローカルファイルシステム",
"deviceNotSupport": "現在のデバイスはサポートされていません",
"second": "秒",
"syncInterval": "同期間隔",
"syncIntervalTip": "データが変動しなくなった後に自動的にデータを同期します",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "現在選択されているのは SiYuan が公式に提供するクラウドストレージサービスで、有料サブスクリプションユーザーのみが利用可能です",
"syncThirdPartyProviderS3Intro": "現在選択されているのは Amazon S3 プロトコルに準拠したサードパーティのクラウドストレージサービスです (例: <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>、<a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>、<a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "現在選択されているのは WebDAV プロトコルに対応したサードパーティのクラウドストレージサービスです。このプロトコルはパフォーマンスが低く安定性に欠けるため、S3 サービスを優先して選択することをお勧めします",
"syncThirdPartyProviderLocalIntro": "現在、ローカルファイルシステムが提供するストレージサービスが選択されています。<code class='fn__code'>Endpoint</code>フィールドにローカルフォルダの完全なパスを入力してください",
"syncThirdPartyProviderTip": "この機能を使用する前にサードパーティのクラウドストレージサービスの技術的な制限と請求項目に注意してください: <div class=\"b3-label__text\"><ul class='fn__list'><li>インターフェース呼び出し頻度や帯域幅などの技術的制限</li><li>ストレージ容量やトラフィックなどの請求項目</li><li>利用規約と可用性の保証</li></ul></div><div class='fn__hr'></div>免責事項: 詳細は SiYuan が使用するオープンソースライセンス AGPLv3 の関連規約を参照してください",
"syncProvider": "クラウドストレージサービスプロバイダー",
"syncProviderTip": "選択したプロバイダーのクラウドストレージサービスがクラウド同期とバックアップ機能を実現するために使用されます",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "Lokalny system plików",
"deviceNotSupport": "Bieżące urządzenie nie jest obsługiwane",
"second": "sekunda",
"syncInterval": "interwał synchronizacji",
"syncIntervalTip": "Automatyczna synchronizacja danych po zaprzestaniu zmian",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "Aktualnie wybrano usługę pamięci w chmurze oficjalnie dostarczaną przez SiYuan, która obsługuje tylko płatnych subskrybentów",
"syncThirdPartyProviderS3Intro": "Wybrano aktualnie jest usługą pamięci w chmurze firmy trzeciej zgodną z protokołem Amazon S3 (np. <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>, <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>, <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "Wybrano obecnie jest usługą pamięci w chmurze firmy trzeciej z protokołem WebDAV. Z powodu słabej wydajności i niewystarczającej stabilności tego protokołu zaleca się najpierw wybranie usługi S3",
"syncThirdPartyProviderLocalIntro": "Obecnie wybrana jest usługa pamięci masowej dostarczana przez lokalny system plików. Wprowadź pełną ścieżkę do lokalnego folderu w polu <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "Przed użyciem tej funkcji proszę zwrócić uwagę na ograniczenia techniczne i pozycje rozliczeniowe usługi pamięci w chmurze firmy trzeciej: <div class=\"b3-label__text\"><ul class='fn__list'><li>Ograniczenia techniczne, takie jak częstotliwość wywołań interfejsów i przepustowość</li><li>Elementy rozliczeniowe, takie jak przestrzeń magazynowa i ruch</li><li>Warunki użytkowania i gwarancja dostępności</li></ul></div><div class='fn__hr'></div> Zastrzeżenie: Aby uzyskać szczegóły, należy się odwołać do odpowiednich warunków w licencji open source AGPLv3 używanej przez SiYuan",
"syncProvider": "Dostawca usługi pamięci w chmurze",
"syncProviderTip": "Jeśli zostanie wybrany, usługa pamięci w chmurze tego dostawcy zostanie wykorzystana do realizacji funkcji synchronizacji i kopii zapasowej w chmurze",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "Локальная файловая система",
"deviceNotSupport": "Текущее устройство не поддерживается",
"second": "секунда",
"syncInterval": "интервал синхронизации",
"syncIntervalTip": "Автоматическая синхронизация данных после прекращения изменений",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "В настоящее время выбрана облачная служба хранения, официально предоставляемая SiYuan, которая поддерживает только пользователей платной подписки",
"syncThirdPartyProviderS3Intro": "В настоящее время выбрана служба облачного хранения третьей стороны, совместимая с протоколом Amazon S3 (например, <a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">Qiniu</a>, <a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">Aliyun OSS</a>, <a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>)",
"syncThirdPartyProviderWebDAVIntro": "В настоящее время выбрана облачная служба хранения, третьей стороны с протоколом WebDAV. Из-за низкой производительности и недостаточной стабильности этого протокола рекомендуется сначала выбрать службу S3",
"syncThirdPartyProviderLocalIntro": "В настоящее время выбрана служба хранения, предоставляемая локальной файловой системой. Введите полный путь к локальной папке в поле <code class='fn__code'>Endpoint</code>",
"syncThirdPartyProviderTip": "Перед использованием этой функции, пожалуйста, обратите внимание на технические ограничения и пункты выставления счетов службы облачного хранения третьей стороны: <div class=\"b3-label__text\"><ul class='fn__list'><li>Технические ограничения, такие как частота вызова интерфейса и пропускная способность</li><li>Пункты выставления счетов, такие как место для хранения и трафик</li><li>Условия использования и гарантия доступности</li></ul></div><div class='fn__hr'></div>Отказ от ответственности: Для получения дополнительных сведений смотрите соответствующие условия в лицензии открытого исходного кода AGPLv3, используемой SiYuan",
"syncProvider": "Поставщик услуги облачного хранения",
"syncProviderTip": "Если выбрано, будет использоваться облачное хранилище этого провайдера для реализации функций синхронизации и резервного копирования в облаке",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "本地檔案系統",
"deviceNotSupport": "當前設備不支援",
"second": "秒",
"syncInterval": "同步間隔",
"syncIntervalTip": "數據不再變動後自動進行數據同步",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "當前選擇的是 SiYuan 官方提供的雲端存儲服務,僅支持付費訂閱用戶使用",
"syncThirdPartyProviderS3Intro": "當前選擇的是 Amazon S3 協議兼容的第三方雲端存儲服務(比如<a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">七牛雲</a>、<a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">阿里雲 OSS</a>、<a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>",
"syncThirdPartyProviderWebDAVIntro": "當前選擇的是 WebDAV 協議的第三方雲端存儲服務。由於該協議性能較差且穩定性不足,建議優先選擇 S3 服務",
"syncThirdPartyProviderLocalIntro": "目前選擇的是本地文件系統提供的儲存服務。請在 <code class='fn__code'>Endpoint</code> 欄位中輸入本地資料夾的完整路徑",
"syncThirdPartyProviderTip": "在使用該特性前,請注意第三方雲端存儲服務的技術限制和計費項目等條款:<div class=\"b3-label__text\"><ul class='fn__list'><li>接口調用頻率、頻寬等技術限制</li><li>存儲空間和流量等計費項目</li><li>使用條款和可用性保障等條款</li></ul></div><div class='fn__hr'></div>免責聲明:詳見思源筆記所使用的開源許可證 AGPLv3 中的相關條款",
"syncProvider": "雲端存儲服務提供商",
"syncProviderTip": "選擇後將使用該提供商的雲端存儲服務實現雲端同步和備份功能",

View File

@ -1,4 +1,6 @@
{
"localFlieSystem": "本地文件系统",
"deviceNotSupport": "当前设备不支持",
"second": "秒",
"syncInterval": "同步间隔",
"syncIntervalTip": "数据不再变动后自动进行数据同步",
@ -475,6 +477,7 @@
"syncOfficialProviderIntro": "当前选择的是 SiYuan 官方提供的云端存储服务,仅支持付费订阅用户使用",
"syncThirdPartyProviderS3Intro": "当前选择的是 Amazon S3 协议兼容的第三方云端存储服务(比如<a href=\"https://s.qiniu.com/VbQfeu\" target=\"_blank\">七牛云</a>、<a href=\"https://www.aliyun.com/product/oss?userCode=yqovuas2\" target=\"_blank\">阿里云 OSS</a>、<a href=\"https://www.cloudflare.com/\" target=\"_blank\">Cloudflare R2</a>",
"syncThirdPartyProviderWebDAVIntro": "当前选择的是 WebDAV 协议的第三方云端存储服务。由于该协议性能较差且稳定性不足,建议优先选择 S3 服务",
"syncThirdPartyProviderLocalIntro": "当前选择的是本地文件系统提供的存储服务。请在 <code class='fn__code'>Endpoint</code> 字段中输入本地文件夹的完整路径",
"syncThirdPartyProviderTip": "在使用该特性前,请注意第三方云端存储服务的技术限制和计费项目等条款:<div class=\"b3-label__text\"><ul class='fn__list'><li>接口调用频率、带宽等技术限制</li><li>存储空间和流量等计费项目</li><li>使用条款和可用性保障等条款</li></ul></div><div class='fn__hr'></div>免责声明:详见思源笔记所使用的开源许可证 AGPLv3 中的相关条款",
"syncProvider": "云端存储服务提供商",
"syncProviderTip": "选择后将使用该提供商的云端存储服务实现云端同步和备份功能",

View File

@ -6,7 +6,7 @@
"id": "20230805232018-hgrq0ju",
"title": "Connect with third-party cloud storage",
"type": "doc",
"updated": "20241216171745"
"updated": "20241231014303"
},
"Children": [
{
@ -56,7 +56,7 @@
"ListData": {},
"Properties": {
"id": "20230805232156-kbi85az",
"updated": "20241216171745"
"updated": "20241231014303"
},
"Children": [
{
@ -229,6 +229,34 @@
]
}
]
},
{
"ID": "20241231014251-chridot",
"Type": "NodeListItem",
"ListData": {
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20241231014251-chridot",
"updated": "20241231014303"
},
"Children": [
{
"ID": "20241231014251-9owrhd5",
"Type": "NodeParagraph",
"Properties": {
"id": "20241231014251-9owrhd5",
"updated": "20241231014303"
},
"Children": [
{
"Type": "NodeText",
"Data": "Local file system"
}
]
}
]
}
]
},

View File

@ -6,7 +6,7 @@
"id": "20230805230131-sn7obzb",
"title": "对接第三方云端存储",
"type": "doc",
"updated": "20241216171525"
"updated": "20241231014122"
},
"Children": [
{
@ -56,7 +56,7 @@
"ListData": {},
"Properties": {
"id": "20230805230746-4q9cmrb",
"updated": "20241216171525"
"updated": "20241231014122"
},
"Children": [
{
@ -219,6 +219,34 @@
]
}
]
},
{
"ID": "20241231014119-rkud23t",
"Type": "NodeListItem",
"ListData": {
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20241231014119-rkud23t",
"updated": "20241231014122"
},
"Children": [
{
"ID": "20241231014119-fdfwv7d",
"Type": "NodeParagraph",
"Properties": {
"id": "20241231014119-fdfwv7d",
"updated": "20241231014122"
},
"Children": [
{
"Type": "NodeText",
"Data": "本地文件系统"
}
]
}
]
}
]
},

View File

@ -6,7 +6,7 @@
"id": "20230805232903-erdoerp",
"title": "對接第三方雲端存儲",
"type": "doc",
"updated": "20241216171627"
"updated": "20241231014235"
},
"Children": [
{
@ -56,7 +56,7 @@
"ListData": {},
"Properties": {
"id": "20230805232945-ugjx8sl",
"updated": "20241216171627"
"updated": "20241231014235"
},
"Children": [
{
@ -229,6 +229,34 @@
]
}
]
},
{
"ID": "20241231014229-xkbbezi",
"Type": "NodeListItem",
"ListData": {
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20241231014229-xkbbezi",
"updated": "20241231014235"
},
"Children": [
{
"ID": "20241231014229-5oi1vuc",
"Type": "NodeParagraph",
"Properties": {
"id": "20241231014229-5oi1vuc",
"updated": "20241231014235"
},
"Children": [
{
"Type": "NodeText",
"Data": "本地檔案系統"
}
]
}
]
}
]
},

View File

@ -7,7 +7,7 @@
"id": "20240530101000-na9sys7",
"title": "サードパーティのクラウドストレージへの接続",
"type": "doc",
"updated": "20241216171841"
"updated": "20241231014328"
},
"Children": [
{
@ -58,7 +58,7 @@
"ListData": {},
"Properties": {
"id": "20240530101000-y5kmw6j",
"updated": "20241216171841"
"updated": "20241231014328"
},
"Children": [
{
@ -244,6 +244,34 @@
]
}
]
},
{
"ID": "20241231014316-b0vcf9w",
"Type": "NodeListItem",
"ListData": {
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20241231014316-b0vcf9w",
"updated": "20241231014328"
},
"Children": [
{
"ID": "20241231014316-5w9cag8",
"Type": "NodeParagraph",
"Properties": {
"id": "20241231014316-5w9cag8",
"updated": "20241231014328"
},
"Children": [
{
"Type": "NodeText",
"Data": "ローカルファイルシステム"
}
]
}
]
}
]
},

View File

@ -6,6 +6,7 @@ import {processSync} from "../dialog/processSystem";
import {getCloudURL} from "./util/about";
import {openByMobile} from "../protyle/util/compatibility";
import {confirmDialog} from "../dialog/confirmDialog";
import {isKernelInMobile} from "../util/functions";
const renderProvider = (provider: number) => {
if (provider === 0) {
@ -124,7 +125,7 @@ const renderProvider = (provider: number) => {
${window.siyuan.languages.syncThirdPartyProviderWebDAVIntro}
<div class="fn__hr"></div>
<em>${window.siyuan.languages.proFeature}</em>
<div class="fn__hr"></div>
<div class="fn__hr"></div>
${window.siyuan.languages.syncThirdPartyProviderTip}
</div>
<div class="b3-label b3-label--inner fn__flex">
@ -177,6 +178,36 @@ const renderProvider = (provider: number) => {
<button class="b3-button b3-button--outline fn__size200" data-action="exportData" data-type="webdav">
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.export}
</button>
</div>`;
} else if (provider === 4) {
if (isKernelInMobile()) {
return `<div class="b3-label b3-label--inner">
${window.siyuan.languages.syncThirdPartyProviderLocalIntro}
<div class="fn__hr"></div>
<em>${window.siyuan.languages.proFeature}</em>
<div class="fn__hr"></div>
${window.siyuan.languages.deviceNotSupport}
</div>`;
}
return `<div class="b3-label b3-label--inner">
${window.siyuan.languages.syncThirdPartyProviderLocalIntro}
<div class="fn__hr"></div>
<em>${window.siyuan.languages.proFeature}</em>
</div>
<div class="b3-label b3-label--inner fn__flex">
<div class="fn__flex-center fn__size200">Endpoint</div>
<div class="fn__space"></div>
<input id="endpoint" class="b3-text-field fn__block" value="${window.siyuan.config.sync.local.endpoint}">
</div>
<div class="b3-label b3-label--inner fn__flex">
<div class="fn__flex-center fn__size200">Timeout (s)</div>
<div class="fn__space"></div>
<input id="timeout" class="b3-text-field fn__block" type="number" min="7" max="300" value="${window.siyuan.config.sync.local.timeout}">
</div>
<div class="b3-label b3-label--inner fn__flex">
<div class="fn__flex-center fn__size200">Concurrent Reqs</div>
<div class="fn__space"></div>
<input id="localConcurrentReqs" class="b3-text-field fn__block" type="number" min="1" max="1024" value="${window.siyuan.config.sync.local.concurrentReqs}">
</div>`;
}
return "";
@ -326,6 +357,39 @@ const bindProviderEvent = () => {
fetchPost("/api/sync/setSyncProviderWebDAV", {webdav}, () => {
window.siyuan.config.sync.webdav = webdav;
});
} else if (window.siyuan.config.sync.provider === 4) {
let timeout = parseInt((providerPanelElement.querySelector("#timeout") as HTMLInputElement).value, 10);
if (7 > timeout) {
timeout = 7;
}
if (300 < timeout) {
timeout = 300;
}
let concurrentReqs = parseInt((providerPanelElement.querySelector("#localConcurrentReqs") as HTMLInputElement).value, 10);
if (1 > concurrentReqs) {
concurrentReqs = 1;
}
if (1024 < concurrentReqs) {
concurrentReqs = 1024;
}
(providerPanelElement.querySelector("#timeout") as HTMLInputElement).value = timeout.toString();
const local = {
endpoint: (providerPanelElement.querySelector("#endpoint") as HTMLInputElement).value,
timeout: timeout,
concurrentReqs: concurrentReqs,
};
fetchPost("/api/sync/setSyncProviderLocal", {local}, (response) => {
if (response.code === 0) {
window.siyuan.config.sync.local = response.data.local;
const endpoint = providerPanelElement.querySelector<HTMLInputElement>("#endpoint");
if (endpoint) {
endpoint.value = response.data.local.endpoint;
}
} else {
window.siyuan.config.sync.local = local;
}
});
}
});
});
@ -348,6 +412,7 @@ export const repos = {
<option value="0" ${window.siyuan.config.sync.provider === 0 ? "selected" : ""}>SiYuan</option>
<option value="2" ${window.siyuan.config.sync.provider === 2 ? "selected" : ""}>S3</option>
<option value="3" ${window.siyuan.config.sync.provider === 3 ? "selected" : ""}>WebDAV</option>
<option value="4" ${window.siyuan.config.sync.provider === 4 ? "selected" : ""}>${window.siyuan.languages.localFlieSystem}</option>
</select>
</div>
<div id="syncProviderPanel" class="b3-label">

View File

@ -1376,6 +1376,7 @@ declare namespace Config {
*/
synced: number;
webdav: ISyncWebDAV;
local: ISyncLocal;
}
/**
@ -1450,6 +1451,28 @@ declare namespace Config {
username: string;
}
/**
* Local file system related configuration
*/
export interface ISyncLocal {
/**
* The full path of local directory
*
* Examples:
* - Windows: `"D:/path/to/repos/directory"`
* - Unix: `"/path/to/repos/directory"`
*/
endpoint: string;
/**
* Timeout (unit: seconds)
*/
timeout: number;
/**
* Concurrent requests.
*/
concurrentReqs: number;
}
/**
* System related information
*/
@ -1474,6 +1497,7 @@ declare namespace Config {
* - `docker`: Docker container
* - `android`: Android device
* - `ios`: iOS device
* - `harmony`: HarmonyOS device
* - `std`: Desktop Electron environment
*/
container: TSystemContainer;

View File

@ -1,16 +1,28 @@
const CONTAINER_BACKEND_SET = new Set(["docker", "ios", "android", "harmony"]);
const MOBILE_BACKEND_SET = new Set(["ios", "android", "harmony"]);
export const isKernelInContainer = (): boolean => {
return CONTAINER_BACKEND_SET.has(window.siyuan.config.system.container);
};
export const isKernelInMobile = (): boolean => {
return MOBILE_BACKEND_SET.has(window.siyuan.config.system.container);
};
export const isMobile = () => {
return document.getElementById("sidebar") ? true : false;
};
// "windows" | "linux" | "darwin" | "docker" | "android" | "ios" | "harmony"
export const getBackend = () => {
if (["docker", "ios", "android", "harmony"].includes(window.siyuan.config.system.container)) {
if (isKernelInContainer()) {
return window.siyuan.config.system.container;
} else {
return window.siyuan.config.system.os;
}
};
// "desktop" | "desktop-window" | "mobile" | "browser-desktop" | "browser-mobile"
export const getFrontend = () => {
/// #if MOBILE

View File

@ -245,6 +245,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/sync/setSyncProvider", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncProvider)
ginServer.Handle("POST", "/api/sync/setSyncProviderS3", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncProviderS3)
ginServer.Handle("POST", "/api/sync/setSyncProviderWebDAV", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncProviderWebDAV)
ginServer.Handle("POST", "/api/sync/setSyncProviderLocal", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncProviderLocal)
ginServer.Handle("POST", "/api/sync/setCloudSyncDir", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setCloudSyncDir)
ginServer.Handle("POST", "/api/sync/createCloudSyncDir", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, createCloudSyncDir)
ginServer.Handle("POST", "/api/sync/removeCloudSyncDir", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, removeCloudSyncDir)

View File

@ -667,6 +667,45 @@ func setSyncProviderWebDAV(c *gin.Context) {
}
}
func setSyncProviderLocal(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
localArg := arg["local"].(interface{})
data, err := gulu.JSON.MarshalJSON(localArg)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = map[string]interface{}{"closeTimeout": 5000}
return
}
local := &conf.Local{}
if err = gulu.JSON.UnmarshalJSON(data, local); err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = map[string]interface{}{"closeTimeout": 5000}
return
}
err = model.SetSyncProviderLocal(local)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = map[string]interface{}{"closeTimeout": 5000}
return
}
ret.Data = map[string]interface{}{
"local": local,
}
}
func setCloudSyncDir(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)

View File

@ -28,6 +28,7 @@ type Sync struct {
Provider int `json:"provider"` // 云端存储服务提供者
S3 *S3 `json:"s3"` // S3 对象存储服务配置
WebDAV *WebDAV `json:"webdav"` // WebDAV 服务配置
Local *Local `json:"local"` // 本地文件系统 服务配置
}
func NewSync() *Sync {
@ -63,10 +64,17 @@ type WebDAV struct {
ConcurrentReqs int `json:"concurrentReqs"` // 并发请求数
}
type Local struct {
Endpoint string `json:"endpoint"` // 服务端点 (本地文件系统目录)
Timeout int `json:"timeout"` // 超时时间,单位:秒
ConcurrentReqs int `json:"concurrentReqs"` // 并发请求数
}
const (
ProviderSiYuan = 0 // ProviderSiYuan 为思源官方提供的云端存储服务
ProviderS3 = 2 // ProviderS3 为 S3 协议对象存储提供的云端存储服务
ProviderWebDAV = 3 // ProviderWebDAV 为 WebDAV 协议提供的云端存储服务
ProviderLocal = 4 // ProviderLocal 为本地文件系统提供的存储服务
)
func ProviderToStr(provider int) string {
@ -77,6 +85,8 @@ func ProviderToStr(provider int) string {
return "S3"
case ProviderWebDAV:
return "WebDAV"
case ProviderLocal:
return "Local File System"
}
return "Unknown"
}

View File

@ -360,6 +360,13 @@ func InitConf() {
Conf.Sync.WebDAV.Endpoint = util.NormalizeEndpoint(Conf.Sync.WebDAV.Endpoint)
Conf.Sync.WebDAV.Timeout = util.NormalizeTimeout(Conf.Sync.WebDAV.Timeout)
Conf.Sync.WebDAV.ConcurrentReqs = util.NormalizeConcurrentReqs(Conf.Sync.WebDAV.ConcurrentReqs, conf.ProviderWebDAV)
if nil == Conf.Sync.Local {
Conf.Sync.Local = &conf.Local{}
}
Conf.Sync.Local.Endpoint = util.NormalizeLocalPath(Conf.Sync.Local.Endpoint)
Conf.Sync.Local.Timeout = util.NormalizeTimeout(Conf.Sync.Local.Timeout)
Conf.Sync.Local.ConcurrentReqs = util.NormalizeConcurrentReqs(Conf.Sync.Local.ConcurrentReqs, conf.ProviderLocal)
if util.ContainerDocker == util.Container {
Conf.Sync.Perception = false
}

View File

@ -803,7 +803,7 @@ func DownloadCloudSnapshot(tag, id string) (err error) {
util.PushErrMsg(Conf.Language(29), 5000)
return
}
case conf.ProviderWebDAV, conf.ProviderS3:
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
util.PushErrMsg(Conf.Language(214), 5000)
return
@ -845,7 +845,7 @@ func UploadCloudSnapshot(tag, id string) (err error) {
util.PushErrMsg(Conf.Language(29), 5000)
return
}
case conf.ProviderWebDAV, conf.ProviderS3:
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
util.PushErrMsg(Conf.Language(214), 5000)
return
@ -891,7 +891,7 @@ func RemoveCloudRepoTag(tag string) (err error) {
util.PushErrMsg(Conf.Language(29), 5000)
return
}
case conf.ProviderWebDAV, conf.ProviderS3:
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
util.PushErrMsg(Conf.Language(214), 5000)
return
@ -923,7 +923,7 @@ func GetCloudRepoTagSnapshots() (ret []*dejavu.Log, err error) {
util.PushErrMsg(Conf.Language(29), 5000)
return
}
case conf.ProviderWebDAV, conf.ProviderS3:
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
util.PushErrMsg(Conf.Language(214), 5000)
return
@ -959,7 +959,7 @@ func GetCloudRepoSnapshots(page int) (ret []*dejavu.Log, pageCount, totalCount i
util.PushErrMsg(Conf.Language(29), 5000)
return
}
case conf.ProviderWebDAV, conf.ProviderS3:
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
util.PushErrMsg(Conf.Language(214), 5000)
return
@ -1845,6 +1845,8 @@ func newRepository() (ret *dejavu.Repo, err error) {
webdavClient.SetTimeout(time.Duration(cloudConf.WebDAV.Timeout) * time.Second)
webdavClient.SetTransport(httpclient.NewTransport(cloudConf.WebDAV.SkipTlsVerify))
cloudRepo = cloud.NewWebDAV(&cloud.BaseCloud{Conf: cloudConf}, webdavClient)
case conf.ProviderLocal:
cloudRepo = cloud.NewLocal(&cloud.BaseCloud{Conf: cloudConf})
default:
err = fmt.Errorf("unknown cloud provider [%d]", Conf.Sync.Provider)
return
@ -2129,6 +2131,12 @@ func buildCloudConf() (ret *cloud.Conf, err error) {
Timeout: Conf.Sync.WebDAV.Timeout,
ConcurrentReqs: Conf.Sync.WebDAV.ConcurrentReqs,
}
case conf.ProviderLocal:
ret.Local = &cloud.ConfLocal{
Endpoint: Conf.Sync.Local.Endpoint,
Timeout: Conf.Sync.Local.Timeout,
ConcurrentReqs: Conf.Sync.Local.ConcurrentReqs,
}
default:
err = fmt.Errorf("invalid provider [%d]", Conf.Sync.Provider)
return

View File

@ -252,7 +252,7 @@ func checkSync(boot, exit, byHand bool) bool {
if !IsSubscriber() {
return false
}
case conf.ProviderWebDAV, conf.ProviderS3:
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
return false
}
@ -471,13 +471,28 @@ func SetSyncProviderWebDAV(webdav *conf.WebDAV) (err error) {
return
}
func SetSyncProviderLocal(local *conf.Local) (err error) {
local.Endpoint = strings.TrimSpace(local.Endpoint)
local.Endpoint = util.NormalizeLocalPath(local.Endpoint)
local.Timeout = util.NormalizeTimeout(local.Timeout)
local.ConcurrentReqs = util.NormalizeConcurrentReqs(local.ConcurrentReqs, conf.ProviderLocal)
Conf.Sync.Local = local
Conf.Save()
return
}
var (
syncLock = sync.Mutex{}
isSyncing = atomic.Bool{}
)
func CreateCloudSyncDir(name string) (err error) {
if conf.ProviderSiYuan != Conf.Sync.Provider {
switch Conf.Sync.Provider {
case conf.ProviderSiYuan, conf.ProviderLocal:
break
default:
err = errors.New(Conf.Language(131))
return
}
@ -502,7 +517,10 @@ func CreateCloudSyncDir(name string) (err error) {
}
func RemoveCloudSyncDir(name string) (err error) {
if conf.ProviderSiYuan != Conf.Sync.Provider {
switch Conf.Sync.Provider {
case conf.ProviderSiYuan, conf.ProviderLocal:
break
default:
err = errors.New(Conf.Language(131))
return
}
@ -678,6 +696,9 @@ func isProviderOnline(byHand bool) (ret bool) {
checkURL = Conf.Sync.WebDAV.Endpoint
skipTlsVerify = Conf.Sync.WebDAV.SkipTlsVerify
timeout = Conf.Sync.WebDAV.Timeout * 1000
case conf.ProviderLocal:
checkURL = "file://" + Conf.Sync.Local.Endpoint
timeout = Conf.Sync.Local.Timeout * 1000
default:
logging.LogWarnf("unknown provider: %d", Conf.Sync.Provider)
return false

View File

@ -20,6 +20,7 @@ import (
"net"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
@ -73,14 +74,19 @@ func IsLocalOrigin(origin string) bool {
}
func IsOnline(checkURL string, skipTlsVerify bool, timeout int) bool {
_, err := url.Parse(checkURL)
if "" == checkURL {
return false
}
u, err := url.Parse(checkURL)
if err != nil {
logging.LogWarnf("invalid check URL [%s]", checkURL)
return false
}
if "" == checkURL {
return false
if u.Scheme == "file" {
filePath := strings.TrimPrefix(checkURL, "file://")
_, err := os.Stat(filePath)
return err == nil
}
if isOnline(checkURL, skipTlsVerify, timeout) {

View File

@ -188,16 +188,39 @@ func GetChildDocDepth(treeAbsPath string) (ret int) {
}
func NormalizeConcurrentReqs(concurrentReqs int, provider int) int {
if 1 > concurrentReqs {
if 2 == provider { // S3
return 8
} else if 3 == provider { // WebDAV
return 1
switch provider {
case 0: // SiYuan
switch {
case concurrentReqs < 1:
concurrentReqs = 8
case concurrentReqs > 16:
concurrentReqs = 16
default:
}
case 2: // S3
switch {
case concurrentReqs < 1:
concurrentReqs = 8
case concurrentReqs > 16:
concurrentReqs = 16
default:
}
case 3: // WebDAV
switch {
case concurrentReqs < 1:
concurrentReqs = 1
case concurrentReqs > 16:
concurrentReqs = 16
default:
}
case 4: // Local File System
switch {
case concurrentReqs < 1:
concurrentReqs = 16
case concurrentReqs > 1024:
concurrentReqs = 1024
default:
}
return 8
}
if 16 < concurrentReqs {
return 16
}
return concurrentReqs
}
@ -229,6 +252,18 @@ func NormalizeEndpoint(endpoint string) string {
return endpoint
}
func NormalizeLocalPath(endpoint string) string {
endpoint = strings.TrimSpace(endpoint)
if "" == endpoint {
return ""
}
endpoint = filepath.ToSlash(filepath.Clean(endpoint))
if !strings.HasSuffix(endpoint, "/") {
endpoint = endpoint + "/"
}
return endpoint
}
func FilterMoveDocFromPaths(fromPaths []string, toPath string) (ret []string) {
tmp := FilterSelfChildDocs(fromPaths)
for _, fromPath := range tmp {