204 lines
7.0 KiB
Dart
204 lines
7.0 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:go_router/go_router.dart';
|
||
import '../providers/gitea_sync_provider.dart';
|
||
|
||
class GiteaSyncSettingsScreen extends ConsumerStatefulWidget {
|
||
const GiteaSyncSettingsScreen({super.key});
|
||
|
||
@override
|
||
ConsumerState<GiteaSyncSettingsScreen> createState() => _GiteaSyncSettingsScreenState();
|
||
}
|
||
|
||
class _GiteaSyncSettingsScreenState extends ConsumerState<GiteaSyncSettingsScreen> {
|
||
final _formKey = GlobalKey<FormState>();
|
||
final _urlCtrl = TextEditingController(text: 'http://git.a-crm.controlsystem.kz');
|
||
final _tokenCtrl = TextEditingController();
|
||
final _ownerCtrl = TextEditingController(text: 'Alexyz');
|
||
final _repoCtrl = TextEditingController(text: 'CMMNANAXE-CRM');
|
||
|
||
bool _testing = false;
|
||
|
||
@override
|
||
void dispose() {
|
||
_urlCtrl.dispose();
|
||
_tokenCtrl.dispose();
|
||
_ownerCtrl.dispose();
|
||
_repoCtrl.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
Future<void> _testAndSave() async {
|
||
if (!_formKey.currentState!.validate()) return;
|
||
|
||
setState(() => _testing = true);
|
||
|
||
final notifier = ref.read(mindmapSyncProvider.notifier);
|
||
try {
|
||
await notifier.configure(
|
||
baseUrl: _urlCtrl.text.trim(),
|
||
token: _tokenCtrl.text.trim(),
|
||
owner: _ownerCtrl.text.trim(),
|
||
repo: _repoCtrl.text.trim(),
|
||
);
|
||
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('Подключение к Gitea установлено')),
|
||
);
|
||
}
|
||
} catch (e) {
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(content: Text('Ошибка: $e'), backgroundColor: Colors.red),
|
||
);
|
||
}
|
||
} finally {
|
||
if (mounted) setState(() => _testing = false);
|
||
}
|
||
}
|
||
|
||
Future<void> _syncNow() async {
|
||
setState(() => _testing = true);
|
||
final notifier = ref.read(mindmapSyncProvider.notifier);
|
||
try {
|
||
await notifier.syncFromGitea();
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('Синхронизация завершена')),
|
||
);
|
||
}
|
||
} catch (e) {
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(content: Text('Ошибка синхронизации: $e'), backgroundColor: Colors.red),
|
||
);
|
||
}
|
||
} finally {
|
||
if (mounted) setState(() => _testing = false);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final state = ref.watch(mindmapSyncProvider);
|
||
|
||
return Scaffold(
|
||
appBar: AppBar(
|
||
title: const Text('Синхронизация с Gitea'),
|
||
leading: IconButton(
|
||
icon: const Icon(Icons.arrow_back),
|
||
onPressed: () => context.pop(),
|
||
),
|
||
),
|
||
body: Padding(
|
||
padding: const EdgeInsets.all(16.0),
|
||
child: Form(
|
||
key: _formKey,
|
||
child: ListView(
|
||
children: [
|
||
// Статус
|
||
Card(
|
||
child: ListTile(
|
||
leading: Icon(
|
||
state.isConfigured ? Icons.cloud_done : Icons.cloud_off,
|
||
color: state.isConfigured ? Colors.green : Colors.grey,
|
||
),
|
||
title: Text(
|
||
state.isConfigured ? 'Подключено к Gitea' : 'Не подключено',
|
||
style: Theme.of(context).textTheme.titleMedium,
|
||
),
|
||
subtitle: state.isSyncing
|
||
? const Text('Синхронизация...')
|
||
: state.error != null
|
||
? Text('Ошибка: ${state.error}')
|
||
: const Text('Настройте подключение ниже'),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
|
||
// URL
|
||
TextFormField(
|
||
controller: _urlCtrl,
|
||
decoration: const InputDecoration(
|
||
labelText: 'Gitea URL',
|
||
hintText: 'http://git.a-crm.controlsystem.kz',
|
||
border: OutlineInputBorder(),
|
||
prefixIcon: Icon(Icons.link),
|
||
),
|
||
validator: (v) => v == null || v.isEmpty ? 'Укажите URL' : null,
|
||
),
|
||
const SizedBox(height: 12),
|
||
|
||
// Token
|
||
TextFormField(
|
||
controller: _tokenCtrl,
|
||
decoration: const InputDecoration(
|
||
labelText: 'Access Token',
|
||
hintText: 'Ваш токен из Gitea (Settings → Applications)',
|
||
border: OutlineInputBorder(),
|
||
prefixIcon: Icon(Icons.key),
|
||
),
|
||
obscureText: true,
|
||
validator: (v) => v == null || v.isEmpty ? 'Укажите токен' : null,
|
||
),
|
||
const SizedBox(height: 12),
|
||
|
||
// Owner
|
||
TextFormField(
|
||
controller: _ownerCtrl,
|
||
decoration: const InputDecoration(
|
||
labelText: 'Owner (пользователь/организация)',
|
||
hintText: 'Alexyz',
|
||
border: OutlineInputBorder(),
|
||
prefixIcon: Icon(Icons.person),
|
||
),
|
||
validator: (v) => v == null || v.isEmpty ? 'Укажите владельца' : null,
|
||
),
|
||
const SizedBox(height: 12),
|
||
|
||
// Repo
|
||
TextFormField(
|
||
controller: _repoCtrl,
|
||
decoration: const InputDecoration(
|
||
labelText: 'Repository',
|
||
hintText: 'CMMNANAXE-CRM',
|
||
border: OutlineInputBorder(),
|
||
prefixIcon: Icon(Icons.folder),
|
||
),
|
||
validator: (v) => v == null || v.isEmpty ? 'Укажите репозиторий' : null,
|
||
),
|
||
const SizedBox(height: 24),
|
||
|
||
// Кнопки
|
||
ElevatedButton.icon(
|
||
onPressed: _testing ? null : _testAndSave,
|
||
icon: _testing
|
||
? const SizedBox(
|
||
width: 20,
|
||
height: 20,
|
||
child: CircularProgressIndicator(strokeWidth: 2),
|
||
)
|
||
: const Icon(Icons.save),
|
||
label: const Text('Сохранить и проверить'),
|
||
),
|
||
const SizedBox(height: 12),
|
||
|
||
if (state.isConfigured)
|
||
ElevatedButton.icon(
|
||
onPressed: _testing ? null : _syncNow,
|
||
icon: const Icon(Icons.sync),
|
||
label: const Text('Синхронизировать сейчас'),
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: Colors.green,
|
||
foregroundColor: Colors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|