Anonymous
Ошибка сборки Flutter: плагин [id: 'org.gradle.kotlin.kotlin-dsl', версия: '5.1.2'] не найден
Сообщение
Anonymous » 21 окт 2025, 15:25
Я получаю сообщение об ошибке сборки Gradle при попытке собрать проект Flutter в Windows:
Код: Выделить всё
FAILURE: Build failed with an exception.
Where:
Build file 'C:\Users\\develop\flutter\packages\flutter_tools\gradle\build.gradle.kts' line: 7
What went wrong:
Plugin [id: 'org.gradle.kotlin.kotlin-dsl', version: '5.1.2'] was not found in any of the following sources:
Что я пробовал:
и удалил папки .gradle и build
Переустановил Gradle и Android SDK
Переустановил Flutter
Проверил подключение к Интернету и брандмауэр
Я пробовал выполнить поиск в Google, но все либо предлагает чистую сборку удалить файлы .gradle или другие файлы сборки, но все равно безуспешно
Ошибка по-прежнему возникает при запуске:
Окружающая среда:
Код: Выделить всё
Flutter 3.35.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 9f455d2486 (2025-10-08)
Engine • hash a5f2c36e367c13f868cfe98db5806f562c52c35e
Tools • Dart 3.9.2 • DevTools 2.48.0
Gradle version: 8.12
Минимально воспроизводимый пример:
Код: Выделить всё
my_app/
├─ android/
│ ├─ build.gradle.kts
│ └─ gradle/wrapper/gradle-wrapper.properties
├─ lib/
│ └─ main.dart
└─ pubspec.yaml
Код: Выделить всё
android/build.gradle.kts:
plugins {
id("org.gradle.kotlin.kotlin-dsl") version "5.1.2"
}
repositories {
google()
mavenCentral()
}
tasks.register("hello") {
doLast {
println("Hello from Gradle")
}
}
Код: Выделить всё
android/gradle/wrapper/gradle-wrapper.properties:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Код: Выделить всё
lib/main.dart:
import 'package:flutter/material.dart';
import 'features/auth/login_page.dart';
void main() {
runApp(const Milog());
}
class Milog extends StatelessWidget {
const Milog({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const LoginPage(),
);
}
}
страница входа
Код: Выделить всё
import 'package:flutter/material.dart';
import 'forgot_password_page.dart';
// --- Style Variables ---
const kPrimaryGradient = LinearGradient(
colors: [Color(0xFF667eea), Color(0xFF764ba2)],
);
const kBackgroundGradient = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF667eea), Color(0xFF764ba2), Color(0xFFf093fb)],
);
const kButtonTextColor = Colors.white;
const kButtonShadowColor = Color(0xFF667eea);
const kButtonBorderRadius = 16.0;
const kForgotPasswordColor = Color(0xFF667eea);
const kErrorTextColor = Color(0xFFB00020);
const kInputIconColor = Color(0xFF667eea);
const kInputFillColor = Color(0xFFF7F8FA);
const kInputBorderColor = Color(0xFFE0E0E0);
const kInputBorderRadius = 16.0;
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State createState() => _LoginPageState();
}
class _LoginPageState extends State with TickerProviderStateMixin {
late AnimationController _fadeController;
late AnimationController _slideController;
late Animation _fadeAnimation;
late Animation _slideAnimation;
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _registerNameController = TextEditingController();
final TextEditingController _registerEmailController =
TextEditingController();
final TextEditingController _registerPasswordController =
TextEditingController();
final TextEditingController _registerConfirmController =
TextEditingController();
bool _isLoading = false;
bool _isRegisterLoading = false;
bool _obscurePassword = true;
bool _obscureConfirmPassword = true;
bool _isLoginMode = true;
String _error = '';
final _authService = _DummyAuthService();
@override
void initState() {
super.initState();
_fadeController = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
);
_slideController = AnimationController(
duration: const Duration(milliseconds: 600),
vsync: this,
);
_fadeAnimation = CurvedAnimation(
parent: _fadeController,
curve: Curves.easeIn,
);
_slideAnimation =
Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate(
CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic),
);
_fadeController.forward();
_slideController.forward();
}
@override
void dispose() {
_fadeController.dispose();
_slideController.dispose();
_emailController.dispose();
_passwordController.dispose();
_registerNameController.dispose();
_registerEmailController.dispose();
_registerPasswordController.dispose();
_registerConfirmController.dispose();
super.dispose();
}
void _toggleMode() {
setState(() {
_isLoginMode = !_isLoginMode;
_error = '';
});
}
Future _login() async {
setState(() {
_isLoading = true;
_error = '';
});
if (_emailController.text.isEmpty || _passwordController.text.isEmpty) {
setState(() {
_error = 'Please enter both email and password';
_isLoading = false;
});
return;
}
final success = await _authService.login(
_emailController.text.trim(),
_passwordController.text.trim(),
);
setState(() => _isLoading = false);
if (!success) {
setState(() => _error = 'Invalid credentials. Please try again.');
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(
children: [
Icon(Icons.check_circle, color: Colors.white),
SizedBox(width: 12),
Text('Login successful! Welcome back.'),
],
),
backgroundColor: Colors.green,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
}
}
Future _register() async {
setState(() {
_isRegisterLoading = true;
_error = '';
});
if (_registerNameController.text.isEmpty ||
_registerEmailController.text.isEmpty ||
_registerPasswordController.text.isEmpty ||
_registerConfirmController.text.isEmpty) {
setState(() {
_error = 'Please fill in all fields';
_isRegisterLoading = false;
});
return;
}
if (_registerPasswordController.text != _registerConfirmController.text) {
setState(() {
_error = 'Passwords do not match';
_isRegisterLoading = false;
});
return;
}
if (_registerPasswordController.text.length < 6) {
setState(() {
_error = 'Password must be at least 6 characters';
_isRegisterLoading = false;
});
return;
}
final success = await _authService.register(
_registerEmailController.text.trim(),
_registerPasswordController.text.trim(),
);
setState(() => _isRegisterLoading = false);
if (!success) {
setState(() => _error = 'Registration failed. Please try again.');
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(
children: [
Icon(Icons.check_circle, color: Colors.white),
SizedBox(width: 12),
Text('Registration successful! You can now log in.'),
],
),
backgroundColor: Colors.green,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
setState(() => _isLoginMode = true);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF667eea), Color(0xFF764ba2), Color(0xFFf093fb)],
),
),
child: SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: FadeTransition(
opacity: _fadeAnimation,
child: SlideTransition(
position: _slideAnimation,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Logo removed
_buildAuthCard(),
],
),
),
),
),
),
),
),
);
}
Widget _buildAuthCard() {
return Container(
constraints: const BoxConstraints(maxWidth: 450),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha((0.2 * 255).toInt()),
blurRadius: 30,
offset: const Offset(0, 15),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: AnimatedSize(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
child: _isLoginMode ? _buildLoginForm() : _buildRegisterForm(),
),
),
);
}
Widget _buildLoginForm() {
return Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Welcome Back',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Color(0xFF2d3436),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Log in to continue',
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
_buildTextField(
controller: _emailController,
label: 'Email',
icon: Icons.email_outlined,
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 16),
_buildTextField(
controller: _passwordController,
label: 'Password',
icon: Icons.lock_outline,
obscureText: _obscurePassword,
suffixIcon: IconButton(
icon: Icon(
_obscurePassword ? Icons.visibility_off : Icons.visibility,
color: Colors.grey,
),
onPressed: () =>
setState(() => _obscurePassword = !_obscurePassword),
),
),
const SizedBox(height: 8),
Align(
alignment: Alignment.centerLeft,
child: TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const ForgotPasswordPage(),
),
);
},
child: const Text(
'Forgot Password?',
style: TextStyle(
color: kForgotPasswordColor,
fontWeight: FontWeight.bold,
),
),
),
),
if (_error.isNotEmpty) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.red.shade200),
),
child: Row(
children: [
Icon(
Icons.error_outline,
color: Colors.red.shade700,
size: 20,
),
const SizedBox(width: 12),
Expanded(
child: Text(
_error,
style: TextStyle(
color: Colors.red.shade700,
fontSize: 14,
),
),
),
],
),
),
],
const SizedBox(height: 24),
_buildGradientButton(
onPressed: _isLoading ? null : _login,
isLoading: _isLoading,
text: 'Login',
),
const SizedBox(height: 24),
_buildToggleButton(),
],
),
);
}
Widget _buildToggleButton() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_isLoginMode
? "Don't have an account? "
: "Already have an account? ",
style: TextStyle(color: Colors.grey[600]),
),
TextButton(
onPressed: _toggleMode,
child: Text(
_isLoginMode ? 'Sign Up' : 'Log In',
style: const TextStyle(
color: Color(0xFF667eea),
fontWeight: FontWeight.bold,
),
),
),
],
);
}
Widget _buildRegisterForm() {
return Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Create Account',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Color(0xFF2d3436),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Sign up to start your adventure',
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
_buildTextField(
controller: _registerNameController,
label: 'Full Name',
icon: Icons.person_outline,
),
const SizedBox(height: 16),
_buildTextField(
controller: _registerEmailController,
label: 'Email',
icon: Icons.email_outlined,
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 16),
_buildTextField(
controller: _registerPasswordController,
label: 'Password',
icon: Icons.lock_outline,
obscureText: _obscurePassword,
suffixIcon: IconButton(
icon: Icon(
_obscurePassword ? Icons.visibility_off : Icons.visibility,
color: Colors.grey,
),
onPressed: () =>
setState(() => _obscurePassword = !_obscurePassword),
),
),
const SizedBox(height: 16),
_buildTextField(
controller: _registerConfirmController,
label: 'Confirm Password',
icon: Icons.lock_outline,
obscureText: _obscureConfirmPassword,
suffixIcon: IconButton(
icon: Icon(
_obscureConfirmPassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.grey,
),
onPressed: () => setState(
() => _obscureConfirmPassword = !_obscureConfirmPassword,
),
),
),
if (_error.isNotEmpty) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.red.shade200),
),
child: Row(
children: [
Icon(
Icons.error_outline,
color: Colors.red.shade700,
size: 20,
),
const SizedBox(width: 12),
Expanded(
child: Text(
_error,
style: TextStyle(
color: Colors.red.shade700,
fontSize: 14,
),
),
),
],
),
),
],
const SizedBox(height: 24),
_buildGradientButton(
onPressed: _isRegisterLoading ? null : _register,
isLoading: _isRegisterLoading,
text: 'Create Account',
),
const SizedBox(height: 24),
_buildToggleButton(),
],
),
);
}
Widget _buildTextField({
required TextEditingController controller,
required String label,
required IconData icon,
bool obscureText = false,
Widget? suffixIcon,
TextInputType? keyboardType,
}) {
return Container(
decoration: BoxDecoration(
color: Colors.grey[50],
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey[200]!),
),
child: TextField(
controller: controller,
obscureText: obscureText,
keyboardType: keyboardType,
decoration: InputDecoration(
prefixIcon: Icon(icon, color: const Color(0xFF667eea)),
suffixIcon: suffixIcon,
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 16,
),
),
),
);
}
Widget _buildGradientButton({
required VoidCallback? onPressed,
required bool isLoading,
required String text,
}) {
return Container(
height: 56,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF667eea), Color(0xFF764ba2)],
),
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Color(0xFF667eea).withAlpha((0.4 * 255).toInt()),
blurRadius: 15,
offset: Offset(0, 8),
),
],
),
child: ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(),
),
child: isLoading
? SizedBox(
height: 24,
width: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2.5,
),
)
: Text(
text,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
);
}
}
class _DummyAuthService {
Future login(String email, String password) async {
await Future.delayed(const Duration(seconds: 1));
return email == 'test@example.com' && password == 'password123';
}
Future register(String email, String password) async {
await Future.delayed(const Duration(seconds: 1));
return email.isNotEmpty && password.length >= 6;
}
}
Команда для воспроизведения:
Ожидаемое поведение: успешная сборка или вывод более четкой ошибки разрешения плагина.
Фактическое поведение:
Код: Выделить всё
Plugin [id: 'org.gradle.kotlin.kotlin-dsl', version: '5.1.2'] was not found in any of the following sources
Происходит как в VS Code, так и в Android Studio (Narwhal).
Подробнее здесь:
https://stackoverflow.com/questions/797 ... sion-5-1-2
1761049505
Anonymous
Я получаю сообщение об ошибке сборки Gradle при попытке собрать проект Flutter в Windows: [code]FAILURE: Build failed with an exception. Where: Build file 'C:\Users\\develop\flutter\packages\flutter_tools\gradle\build.gradle.kts' line: 7 What went wrong: Plugin [id: 'org.gradle.kotlin.kotlin-dsl', version: '5.1.2'] was not found in any of the following sources: [/code] Что я пробовал: [list] [*][code]flutter clean[/code] и удалил папки .gradle и build [*]Переустановил Gradle и Android SDK [*]Переустановил Flutter [*]Проверил подключение к Интернету и брандмауэр [*]Я пробовал выполнить поиск в Google, но все либо предлагает чистую сборку удалить файлы .gradle или другие файлы сборки, но все равно безуспешно [/list] Ошибка по-прежнему возникает при запуске: [code]flutter build apk [/code] Окружающая среда: [code]Flutter 3.35.6 • channel stable • https://github.com/flutter/flutter.git Framework • revision 9f455d2486 (2025-10-08) Engine • hash a5f2c36e367c13f868cfe98db5806f562c52c35e Tools • Dart 3.9.2 • DevTools 2.48.0 Gradle version: 8.12 [/code] Минимально воспроизводимый пример: [code]my_app/ ├─ android/ │ ├─ build.gradle.kts │ └─ gradle/wrapper/gradle-wrapper.properties ├─ lib/ │ └─ main.dart └─ pubspec.yaml [/code] [code]android/build.gradle.kts: plugins { id("org.gradle.kotlin.kotlin-dsl") version "5.1.2" } repositories { google() mavenCentral() } tasks.register("hello") { doLast { println("Hello from Gradle") } } [/code] [code]android/gradle/wrapper/gradle-wrapper.properties: distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists [/code] [code]lib/main.dart: import 'package:flutter/material.dart'; import 'features/auth/login_page.dart'; void main() { runApp(const Milog()); } class Milog extends StatelessWidget { const Milog({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const LoginPage(), ); } } [/code] страница входа [code]import 'package:flutter/material.dart'; import 'forgot_password_page.dart'; // --- Style Variables --- const kPrimaryGradient = LinearGradient( colors: [Color(0xFF667eea), Color(0xFF764ba2)], ); const kBackgroundGradient = LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFF667eea), Color(0xFF764ba2), Color(0xFFf093fb)], ); const kButtonTextColor = Colors.white; const kButtonShadowColor = Color(0xFF667eea); const kButtonBorderRadius = 16.0; const kForgotPasswordColor = Color(0xFF667eea); const kErrorTextColor = Color(0xFFB00020); const kInputIconColor = Color(0xFF667eea); const kInputFillColor = Color(0xFFF7F8FA); const kInputBorderColor = Color(0xFFE0E0E0); const kInputBorderRadius = 16.0; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State with TickerProviderStateMixin { late AnimationController _fadeController; late AnimationController _slideController; late Animation _fadeAnimation; late Animation _slideAnimation; final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final TextEditingController _registerNameController = TextEditingController(); final TextEditingController _registerEmailController = TextEditingController(); final TextEditingController _registerPasswordController = TextEditingController(); final TextEditingController _registerConfirmController = TextEditingController(); bool _isLoading = false; bool _isRegisterLoading = false; bool _obscurePassword = true; bool _obscureConfirmPassword = true; bool _isLoginMode = true; String _error = ''; final _authService = _DummyAuthService(); @override void initState() { super.initState(); _fadeController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); _slideController = AnimationController( duration: const Duration(milliseconds: 600), vsync: this, ); _fadeAnimation = CurvedAnimation( parent: _fadeController, curve: Curves.easeIn, ); _slideAnimation = Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), ); _fadeController.forward(); _slideController.forward(); } @override void dispose() { _fadeController.dispose(); _slideController.dispose(); _emailController.dispose(); _passwordController.dispose(); _registerNameController.dispose(); _registerEmailController.dispose(); _registerPasswordController.dispose(); _registerConfirmController.dispose(); super.dispose(); } void _toggleMode() { setState(() { _isLoginMode = !_isLoginMode; _error = ''; }); } Future _login() async { setState(() { _isLoading = true; _error = ''; }); if (_emailController.text.isEmpty || _passwordController.text.isEmpty) { setState(() { _error = 'Please enter both email and password'; _isLoading = false; }); return; } final success = await _authService.login( _emailController.text.trim(), _passwordController.text.trim(), ); setState(() => _isLoading = false); if (!success) { setState(() => _error = 'Invalid credentials. Please try again.'); } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Row( children: [ Icon(Icons.check_circle, color: Colors.white), SizedBox(width: 12), Text('Login successful! Welcome back.'), ], ), backgroundColor: Colors.green, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ); } } } Future _register() async { setState(() { _isRegisterLoading = true; _error = ''; }); if (_registerNameController.text.isEmpty || _registerEmailController.text.isEmpty || _registerPasswordController.text.isEmpty || _registerConfirmController.text.isEmpty) { setState(() { _error = 'Please fill in all fields'; _isRegisterLoading = false; }); return; } if (_registerPasswordController.text != _registerConfirmController.text) { setState(() { _error = 'Passwords do not match'; _isRegisterLoading = false; }); return; } if (_registerPasswordController.text.length < 6) { setState(() { _error = 'Password must be at least 6 characters'; _isRegisterLoading = false; }); return; } final success = await _authService.register( _registerEmailController.text.trim(), _registerPasswordController.text.trim(), ); setState(() => _isRegisterLoading = false); if (!success) { setState(() => _error = 'Registration failed. Please try again.'); } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Row( children: [ Icon(Icons.check_circle, color: Colors.white), SizedBox(width: 12), Text('Registration successful! You can now log in.'), ], ), backgroundColor: Colors.green, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ); setState(() => _isLoginMode = true); } } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFF667eea), Color(0xFF764ba2), Color(0xFFf093fb)], ), ), child: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: FadeTransition( opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Logo removed _buildAuthCard(), ], ), ), ), ), ), ), ), ); } Widget _buildAuthCard() { return Container( constraints: const BoxConstraints(maxWidth: 450), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: Colors.black.withAlpha((0.2 * 255).toInt()), blurRadius: 30, offset: const Offset(0, 15), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(24), child: AnimatedSize( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, child: _isLoginMode ? _buildLoginForm() : _buildRegisterForm(), ), ), ); } Widget _buildLoginForm() { return Padding( padding: const EdgeInsets.all(32.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( 'Welcome Back', style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Color(0xFF2d3436), ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'Log in to continue', style: TextStyle(fontSize: 14, color: Colors.grey[600]), textAlign: TextAlign.center, ), const SizedBox(height: 32), _buildTextField( controller: _emailController, label: 'Email', icon: Icons.email_outlined, keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 16), _buildTextField( controller: _passwordController, label: 'Password', icon: Icons.lock_outline, obscureText: _obscurePassword, suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, color: Colors.grey, ), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), ), const SizedBox(height: 8), Align( alignment: Alignment.centerLeft, child: TextButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => const ForgotPasswordPage(), ), ); }, child: const Text( 'Forgot Password?', style: TextStyle( color: kForgotPasswordColor, fontWeight: FontWeight.bold, ), ), ), ), if (_error.isNotEmpty) ...[ const SizedBox(height: 16), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.red.shade50, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.red.shade200), ), child: Row( children: [ Icon( Icons.error_outline, color: Colors.red.shade700, size: 20, ), const SizedBox(width: 12), Expanded( child: Text( _error, style: TextStyle( color: Colors.red.shade700, fontSize: 14, ), ), ), ], ), ), ], const SizedBox(height: 24), _buildGradientButton( onPressed: _isLoading ? null : _login, isLoading: _isLoading, text: 'Login', ), const SizedBox(height: 24), _buildToggleButton(), ], ), ); } Widget _buildToggleButton() { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( _isLoginMode ? "Don't have an account? " : "Already have an account? ", style: TextStyle(color: Colors.grey[600]), ), TextButton( onPressed: _toggleMode, child: Text( _isLoginMode ? 'Sign Up' : 'Log In', style: const TextStyle( color: Color(0xFF667eea), fontWeight: FontWeight.bold, ), ), ), ], ); } Widget _buildRegisterForm() { return Padding( padding: const EdgeInsets.all(32.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( 'Create Account', style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Color(0xFF2d3436), ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'Sign up to start your adventure', style: TextStyle(fontSize: 14, color: Colors.grey[600]), textAlign: TextAlign.center, ), const SizedBox(height: 32), _buildTextField( controller: _registerNameController, label: 'Full Name', icon: Icons.person_outline, ), const SizedBox(height: 16), _buildTextField( controller: _registerEmailController, label: 'Email', icon: Icons.email_outlined, keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 16), _buildTextField( controller: _registerPasswordController, label: 'Password', icon: Icons.lock_outline, obscureText: _obscurePassword, suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, color: Colors.grey, ), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), ), const SizedBox(height: 16), _buildTextField( controller: _registerConfirmController, label: 'Confirm Password', icon: Icons.lock_outline, obscureText: _obscureConfirmPassword, suffixIcon: IconButton( icon: Icon( _obscureConfirmPassword ? Icons.visibility_off : Icons.visibility, color: Colors.grey, ), onPressed: () => setState( () => _obscureConfirmPassword = !_obscureConfirmPassword, ), ), ), if (_error.isNotEmpty) ...[ const SizedBox(height: 16), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.red.shade50, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.red.shade200), ), child: Row( children: [ Icon( Icons.error_outline, color: Colors.red.shade700, size: 20, ), const SizedBox(width: 12), Expanded( child: Text( _error, style: TextStyle( color: Colors.red.shade700, fontSize: 14, ), ), ), ], ), ), ], const SizedBox(height: 24), _buildGradientButton( onPressed: _isRegisterLoading ? null : _register, isLoading: _isRegisterLoading, text: 'Create Account', ), const SizedBox(height: 24), _buildToggleButton(), ], ), ); } Widget _buildTextField({ required TextEditingController controller, required String label, required IconData icon, bool obscureText = false, Widget? suffixIcon, TextInputType? keyboardType, }) { return Container( decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey[200]!), ), child: TextField( controller: controller, obscureText: obscureText, keyboardType: keyboardType, decoration: InputDecoration( prefixIcon: Icon(icon, color: const Color(0xFF667eea)), suffixIcon: suffixIcon, border: InputBorder.none, contentPadding: const EdgeInsets.symmetric( horizontal: 20, vertical: 16, ), ), ), ); } Widget _buildGradientButton({ required VoidCallback? onPressed, required bool isLoading, required String text, }) { return Container( height: 56, decoration: BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF667eea), Color(0xFF764ba2)], ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Color(0xFF667eea).withAlpha((0.4 * 255).toInt()), blurRadius: 15, offset: Offset(0, 8), ), ], ), child: ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, shape: RoundedRectangleBorder(), ), child: isLoading ? SizedBox( height: 24, width: 24, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2.5, ), ) : Text( text, style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ); } } class _DummyAuthService { Future login(String email, String password) async { await Future.delayed(const Duration(seconds: 1)); return email == 'test@example.com' && password == 'password123'; } Future register(String email, String password) async { await Future.delayed(const Duration(seconds: 1)); return email.isNotEmpty && password.length >= 6; } } [/code] Команда для воспроизведения: [code]flutter build apk [/code] Ожидаемое поведение: успешная сборка или вывод более четкой ошибки разрешения плагина. Фактическое поведение: [code]Plugin [id: 'org.gradle.kotlin.kotlin-dsl', version: '5.1.2'] was not found in any of the following sources [/code] Происходит как в VS Code, так и в Android Studio (Narwhal). Подробнее здесь: [url]https://stackoverflow.com/questions/79795542/flutter-build-fails-plugin-id-org-gradle-kotlin-kotlin-dsl-version-5-1-2[/url]