2026-08-17 00:43:33 +03:00
import QtQuick
import QtQuick . Controls
import QtQuick . Layouts
2026-09-01 19:25:07 +03:00
import Flora
2026-08-17 00:43:33 +03:00
Dialog {
id: root
property int providerIndex: - 1
property string providerName: ""
property bool connected: false
signal saved ( int index )
readonly property bool isGit: providerIndex <= 2
title: qsTr ( "Подключение: %1" ) . arg ( providerName )
2026-08-17 15:16:19 +03:00
z: 100
modal: false
2026-08-17 00:43:33 +03:00
width: 640
height: 520
anchors.centerIn: parent
2026-08-17 15:16:19 +03:00
closePolicy: Dialog . CloseOnEscape | Dialog . CloseOnPressOutside
2026-09-01 19:25:07 +03:00
background: Rectangle { color: Theme . surface ; border.color: Theme . borderStrong ; radius: 10 }
2026-08-17 00:43:33 +03:00
function defaultUrl ( ) {
switch ( root . providerIndex ) {
case 0 : return "https://github.com"
case 1 : return "https://gitlab.com"
case 2 : return "http://localhost:3000"
case 3 : return "https://nextcloud.local/remote.php/dav/files/USER"
default: return "http://127.0.0.1:8384"
}
}
function tokenName ( ) {
switch ( root . providerIndex ) {
case 0 : return qsTr ( "Токен GitHub (Personal Access Token)" )
case 1 : return qsTr ( "Токен GitLab (PRIVATE-TOKEN)" )
case 2 : return qsTr ( "Токен Gitea (Personal Access Token)" )
case 3 : return qsTr ( "Пароль от Nextcloud" )
default: return qsTr ( "API-ключ Syncthing" )
}
}
Component.onCompleted: { urlField . text = defaultUrl ( ) }
ColumnLayout {
anchors.fill: parent
spacing: 10
2026-09-01 19:25:07 +03:00
anchors.margins: 4
2026-08-17 00:43:33 +03:00
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 150
2026-09-01 19:25:07 +03:00
color: Theme . bgAlt
border.color: Theme . border
radius: 8
2026-08-17 00:43:33 +03:00
Flickable {
anchors.fill: parent
anchors.margins: 8
ScrollBar.vertical: ScrollBar { }
clip: true
contentWidth: width
contentHeight: instText . implicitHeight
Text {
id: instText
2026-09-01 19:25:07 +03:00
width: parent . width - 16
2026-08-17 00:43:33 +03:00
wrapMode: Text . Wrap
textFormat: Text . MarkdownText
2026-09-01 19:25:07 +03:00
color: Theme . textSecondary
linkColor: Theme . accent
onLinkActivated: ( url ) = > Qt . openUrlExternally ( url )
2026-08-17 00:43:33 +03:00
text: root . providerIndex === 0
2026-09-01 19:25:07 +03:00
? "**Как подключить GitHub:**\n\n" + "1. Создайте токен: [github.com/settings/tokens](https://github.com/settings/tokens) — scope **repo**.\n" + "2. Создайте **пустой** репозиторий (без README).\n" + "3. Вставьте токен ниже и нажмите «Проверить».\n"
2026-08-17 00:43:33 +03:00
: root . providerIndex === 1
2026-09-01 19:25:07 +03:00
? "**Как подключить GitLab:**\n\n" + "1. Токен: Настройки → Access Tokens — scope **api**.\n" + "2. Создайте **пустой** репозиторий.\n" + "3. Для self-hosted: укажите адрес инстанса.\n"
2026-08-17 00:43:33 +03:00
: root . providerIndex === 2
2026-09-01 19:25:07 +03:00
? "**Как подключить Gitea:**\n\n" + "1. Токен: Настройки → Приложения → **Создать новый токен** (scope **repo**).\n" + "2. Создайте **пустой** репозиторий.\n"
2026-08-17 00:43:33 +03:00
: root . providerIndex === 3
2026-09-01 19:25:07 +03:00
? "**Как подключить Nextcloud (WebDAV):**\n\n" + "1. Создайте папку для синхронизации (например **Flora**).\n" + "2. Адрес WebDAV: https://ВАШ_ХОСТ/remote.php/dav/files/ВАШ_ЛОГИН/\n" + "3. Укажите логин и пароль.\n"
: "**Как подключить Syncthing:**\n\n" + "1. Установите и запустите Syncthing.\n" + "2. API-ключ: Действия → Настройки → API-ключ.\n" + "3. Адрес по умолчанию: http://127.0.0.1:8384.\n"
2026-08-17 00:43:33 +03:00
}
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 6
2026-09-01 19:25:07 +03:00
Label { text: qsTr ( "Адрес сервера" ) ; color: Theme . textSecondary ; font.bold: true ; font.pixelSize: 11 }
TextField {
id: urlField ; Layout.fillWidth: true
placeholderTextColor: Theme . textFaint
color: Theme . text
background: Rectangle { color: Theme . bgAlt ; border.color: urlField . activeFocus ? Theme.accent : Theme . border ; radius: 6 }
2026-08-17 00:43:33 +03:00
}
2026-09-01 19:25:07 +03:00
Label { visible: root . providerIndex === 3 ; text: qsTr ( "Логин (для WebDAV):" ) ; color: Theme . textSecondary ; font.pixelSize: 11 }
2026-08-17 00:43:33 +03:00
TextField {
id: userField
Layout.fillWidth: true
visible: root . providerIndex === 3
placeholderText: qsTr ( "Логин Nextcloud" )
2026-09-01 19:25:07 +03:00
placeholderTextColor: Theme . textFaint
color: Theme . text
background: Rectangle { color: Theme . bgAlt ; border.color: userField . activeFocus ? Theme.accent : Theme . border ; radius: 6 }
2026-08-17 00:43:33 +03:00
}
2026-09-01 19:25:07 +03:00
Label { text: tokenName ( ) ; color: Theme . textSecondary ; font.bold: true ; font.pixelSize: 11 }
2026-08-17 00:43:33 +03:00
TextField {
id: tokenField
Layout.fillWidth: true
echoMode: TextInput . Password
placeholderText: qsTr ( "Вставьте значение" )
2026-09-01 19:25:07 +03:00
placeholderTextColor: Theme . textFaint
color: Theme . text
background: Rectangle { color: Theme . bgAlt ; border.color: tokenField . activeFocus ? Theme.accent : Theme . border ; radius: 6 }
2026-08-17 00:43:33 +03:00
}
}
2026-09-01 19:25:07 +03:00
Rectangle {
2026-08-17 00:43:33 +03:00
Layout.fillWidth: true
2026-09-01 19:25:07 +03:00
visible: resultLabel . text . length > 0
color: root . connected ? Theme.successBg : Theme . errorBg
border.color: root . connected ? Theme.successText : Theme . errorText
radius: 6
height: resultLabel . implicitHeight + 12
Label {
id: resultLabel
anchors.fill: parent
anchors.margins: 6
wrapMode: Text . Wrap
visible: text . length > 0
color: root . connected ? Theme.successText : Theme . errorText
font.pixelSize: 11
}
2026-08-17 00:43:33 +03:00
}
Item { Layout.fillHeight: true }
RowLayout {
Layout.fillWidth: true
2026-09-01 19:25:07 +03:00
Button { text: qsTr ( "Отмена" ) ; onClicked: root . reject ( ) }
2026-08-17 00:43:33 +03:00
Item { Layout.fillWidth: true }
Button {
text: qsTr ( "Проверить соединение" )
enabled: tokenField . text . length > 0 && ! syncManager . busy
onClicked: {
resultLabel . text = ""
root . connected = false
2026-09-01 19:25:07 +03:00
syncManager . testConnection ( root . providerIndex , urlField . text , userField . text , tokenField . text )
2026-08-17 00:43:33 +03:00
}
}
Button {
text: qsTr ( "Сохранить" )
2026-09-01 19:25:07 +03:00
highlighted: true
2026-08-17 00:43:33 +03:00
enabled: root . connected
onClicked: {
2026-09-01 19:25:07 +03:00
settingsStore . addProvider ( root . providerName , { url: urlField . text , user: userField . text , token: tokenField . text } )
2026-08-17 00:43:33 +03:00
root . saved ( root . providerIndex )
root . accept ( )
}
}
}
2026-09-01 19:25:07 +03:00
BusyIndicator { visible: syncManager . busy ; running: syncManager . busy ; Layout.alignment: Qt . AlignHCenter }
2026-08-17 00:43:33 +03:00
}
Connections {
target: syncManager
function onConnectionResult ( provider , ok , code , title , hint , raw ) {
2026-09-01 19:25:07 +03:00
if ( provider !== root . providerIndex ) return
2026-08-17 00:43:33 +03:00
root . connected = ok
2026-09-01 19:25:07 +03:00
resultLabel . text = ok ? qsTr ( "Соединение установлено. Нажмите «Сохранить»." ) : title + ( hint && hint . length > 0 ? "\n" + hint : "" )
2026-08-17 00:43:33 +03:00
}
}
2026-09-01 19:25:07 +03:00
}