feat: login page with sucessful login authentication into secure shared preferences

This commit is contained in:
sBubshait 2025-07-21 09:36:31 +03:00
parent 930e6e5284
commit 622db644fa
13 changed files with 641 additions and 408 deletions

View File

@ -0,0 +1,9 @@
class ApiConstants {
static const String baseUrl = 'http://localhost:8080';
// Auth endpoints
static const String loginEndpoint = '/login';
// User endpoints
static const String getUserEndpoint = '/getUser';
}

View File

@ -3,6 +3,7 @@ import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'screens/home_screen.dart';
import 'services/notification_service.dart';
import 'services/auth_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@ -28,63 +29,16 @@ class LandingPage extends StatefulWidget {
_LandingPageState createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _slideAnimation;
bool _showBottomSheet = false;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: Duration(milliseconds: 800),
vsync: this,
);
_slideAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _showGetStartedBottomSheet() {
setState(() {
_showBottomSheet = true;
});
_animationController.forward();
class _LandingPageState extends State<LandingPage> {
void _navigateDirectlyToLogin() {
// Request notification permissions on user action
NotificationService().requestPermissionAndSetup();
}
void _hideBottomSheet() {
_animationController.reverse().then((_) {
setState(() {
_showBottomSheet = false;
});
});
}
void _navigateToSignIn() {
Navigator.of(
context,
).push(MaterialPageRoute(builder: (context) => SignInPage()));
}
void _navigateToHome() {
// Request notification permissions on user action
NotificationService().requestPermissionAndSetup();
Navigator.of(
context,
).push(MaterialPageRoute(builder: (context) => HomeScreen()));
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -156,7 +110,7 @@ class _LandingPageState extends State<LandingPage>
width: 280,
height: 56,
child: ElevatedButton(
onPressed: _showGetStartedBottomSheet,
onPressed: _navigateDirectlyToLogin,
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF6A4C93),
foregroundColor: Colors.white,
@ -183,25 +137,6 @@ class _LandingPageState extends State<LandingPage>
),
SizedBox(height: 24),
// Login link
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: _navigateToHome,
child: Text(
'Skip to Home',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
decoration: TextDecoration.underline,
),
),
),
],
),
],
),
),
@ -209,158 +144,6 @@ class _LandingPageState extends State<LandingPage>
],
),
),
// Bottom sheet overlay
if (_showBottomSheet)
AnimatedBuilder(
animation: _slideAnimation,
builder: (context, child) {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Transform.translate(
offset: Offset(0, _slideAnimation.value * 400),
child: Container(
height: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 20,
offset: Offset(0, -5),
),
],
),
child: Column(
children: [
// Handle bar
Container(
margin: EdgeInsets.only(top: 12),
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(2),
),
),
// Close button
Align(
alignment: Alignment.topRight,
child: IconButton(
onPressed: _hideBottomSheet,
icon: Icon(Icons.close, color: Colors.grey[600]),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Welcome In',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
SizedBox(height: 12),
Text(
'Join your community.. change your social life!',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.grey[600],
),
),
SizedBox(height: 40),
// Sign Up button
Container(
width: double.infinity,
height: 56,
child: ElevatedButton(
onPressed: () {
// Handle sign up
ScaffoldMessenger.of(
context,
).showSnackBar(
SnackBar(
content: Text('Sign Up pressed'),
),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF6A4C93),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
12,
),
),
elevation: 2,
),
child: Text(
'Sign Up Now',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
),
SizedBox(height: 16),
// Login button
Container(
width: double.infinity,
height: 56,
child: OutlinedButton(
onPressed: _navigateToSignIn,
style: OutlinedButton.styleFrom(
foregroundColor: Color(0xFF6A4C93),
side: BorderSide(
color: Color(0xFF6A4C93),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
12,
),
),
),
child: Text(
'Login',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
),
),
],
),
),
),
);
},
),
],
),
);
@ -379,6 +162,72 @@ class _SignInPageState extends State<SignInPage> {
bool _isPasswordVisible = false;
bool _isLoading = false;
void _showHelpBottomSheet() {
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
),
builder: (context) => Container(
padding: EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(2),
),
),
SizedBox(height: 24),
Icon(Icons.contact_support, size: 48, color: Color(0xFF6A4C93)),
SizedBox(height: 16),
Text(
'Need Help?',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
SizedBox(height: 16),
Text(
'For account creation or password reset, please contact ERP Management Group from your Aramco email address.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.grey[700],
height: 1.4,
),
),
SizedBox(height: 24),
Container(
width: double.infinity,
child: ElevatedButton(
onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF6A4C93),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
padding: EdgeInsets.symmetric(vertical: 16),
),
child: Text(
'Got It',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
),
SizedBox(height: 16),
],
),
),
);
}
@override
void dispose() {
_emailController.dispose();
@ -392,19 +241,44 @@ class _SignInPageState extends State<SignInPage> {
_isLoading = true;
});
// Simulate API call
await Future.delayed(Duration(seconds: 2));
final result = await AuthService.login(
_emailController.text.trim(),
_passwordController.text,
);
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Sign in successful!')));
if (result['success'] == true) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => HomeScreen()),
);
} else {
_showErrorAlert(result['message'] ?? 'Login failed');
}
}
}
void _showErrorAlert(String message) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Login Failed'),
content: Text(message),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(
'OK',
style: TextStyle(color: Color(0xFF6A4C93)),
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -493,7 +367,7 @@ class _SignInPageState extends State<SignInPage> {
SizedBox(height: 8),
Text(
'Sign in to your account',
'Sign in to socialize with your colleagues\nand transform your social life!',
style: TextStyle(
fontSize: 16,
color: Colors.grey[600],
@ -575,13 +449,7 @@ class _SignInPageState extends State<SignInPage> {
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Forgot password pressed'),
),
);
},
onPressed: _showHelpBottomSheet,
child: Text(
'Forgot Password?',
style: TextStyle(
@ -625,7 +493,7 @@ class _SignInPageState extends State<SignInPage> {
SizedBox(height: 20),
// Sign up link
// Contact link for new accounts
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@ -634,13 +502,9 @@ class _SignInPageState extends State<SignInPage> {
style: TextStyle(color: Colors.grey[600]),
),
GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Sign up pressed')),
);
},
onTap: _showHelpBottomSheet,
child: Text(
'Sign Up',
'Contact Support',
style: TextStyle(
color: Color(0xFF6A4C93),
fontWeight: FontWeight.w600,

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../services/notification_service.dart';
import '../../services/user_service.dart';
class ProfilePage extends StatefulWidget {
@override
@ -11,6 +12,8 @@ class _ProfilePageState extends State<ProfilePage> {
String? fcmToken;
final TextEditingController _tokenController = TextEditingController();
bool isLoading = false;
Map<String, dynamic>? userData;
bool isLoadingUser = true;
final List<Map<String, dynamic>> mockUserPosts = [
{
@ -46,6 +49,7 @@ class _ProfilePageState extends State<ProfilePage> {
void initState() {
super.initState();
_loadFCMToken();
_loadUserData();
}
@override
@ -75,6 +79,43 @@ class _ProfilePageState extends State<ProfilePage> {
}
}
Future<void> _loadUserData() async {
setState(() {
isLoadingUser = true;
});
final result = await UserService.getCurrentUser();
setState(() {
isLoadingUser = false;
if (result['success'] == true) {
userData = result['data'];
} else {
userData = null;
_showErrorAlert(result['message'] ?? 'Failed to load user data');
}
});
}
void _showErrorAlert(String message) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Error'),
content: Text(message),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(
'OK',
style: TextStyle(color: Color(0xFF6A4C93)),
),
),
],
),
);
}
Future<void> _copyToClipboard() async {
if (fcmToken != null && fcmToken!.isNotEmpty) {
await Clipboard.setData(ClipboardData(text: fcmToken!));
@ -119,200 +160,232 @@ class _ProfilePageState extends State<ProfilePage> {
padding: EdgeInsets.all(24),
child: Column(
children: [
CircleAvatar(
radius: 50,
backgroundColor: Color(0xFF6A4C93),
child: Text(
'A',
if (isLoadingUser)
CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF6A4C93)),
)
else if (userData != null) ...[
CircleAvatar(
radius: 50,
backgroundColor: Color(0xFF6A4C93),
child: Text(
(userData!['displayName'] ?? 'U').substring(0, 1).toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 36,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(height: 16),
Text(
userData!['displayName'] ?? 'Unknown User',
style: TextStyle(
color: Colors.white,
fontSize: 36,
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
),
SizedBox(height: 16),
Text(
'Abu Norah',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black87,
SizedBox(height: 4),
Text(
'@${userData!['username'] ?? 'unknown'}',
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
),
),
SizedBox(height: 4),
Text(
'@yasser_hajri',
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
),
] else ...[
Icon(
Icons.error_outline,
size: 50,
color: Colors.grey[400],
),
SizedBox(height: 16),
Text(
'Failed to load user data',
style: TextStyle(
fontSize: 18,
color: Colors.grey[600],
),
),
SizedBox(height: 8),
ElevatedButton(
onPressed: _loadUserData,
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF6A4C93),
foregroundColor: Colors.white,
),
child: Text('Retry'),
),
],
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text(
'${mockUserPosts.length}',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF6A4C93),
),
),
Text(
'Posts',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
Column(
children: [
Text(
'127',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF6A4C93),
),
),
Text(
'Followers',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
],
),
],
),
),
Container(
height: 1,
color: Colors.grey[200],
margin: EdgeInsets.symmetric(horizontal: 16),
),
SizedBox(height: 16),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: mockUserPosts.length,
itemBuilder: (context, index) {
final post = mockUserPosts[index];
return Container(
margin: EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: Offset(0, 2),
),
],
),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
if (userData != null)
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
Column(
children: [
CircleAvatar(
radius: 16,
backgroundColor: Color(0xFF6A4C93),
child: Text(
'J',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14,
),
Text(
'${mockUserPosts.length}',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF6A4C93),
),
),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Abu Norah',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14,
color: Colors.black87,
),
),
Text(
post['timestamp'],
style: TextStyle(
color: Colors.grey[600],
fontSize: 12,
),
),
],
Text(
'Posts',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
SizedBox(height: 12),
Text(
post['content'],
style: TextStyle(
fontSize: 15,
height: 1.4,
color: Colors.black87,
),
),
SizedBox(height: 12),
Row(
Column(
children: [
Icon(
post['isLiked']
? Icons.favorite
: Icons.favorite_border,
color: post['isLiked']
? Colors.red
: Colors.grey[600],
size: 20,
),
SizedBox(width: 4),
Text(
'${post['likes']}',
'127',
style: TextStyle(
color: Colors.grey[700],
fontSize: 14,
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF6A4C93),
),
),
SizedBox(width: 16),
Icon(
Icons.chat_bubble_outline,
color: Colors.grey[600],
size: 20,
),
SizedBox(width: 4),
Text(
'${post['comments']}',
'Followers',
style: TextStyle(
color: Colors.grey[700],
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
],
),
),
);
},
],
),
),
if (userData != null) ...[
Container(
height: 1,
color: Colors.grey[200],
margin: EdgeInsets.symmetric(horizontal: 16),
),
SizedBox(height: 16),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: mockUserPosts.length,
itemBuilder: (context, index) {
final post = mockUserPosts[index];
return Container(
margin: EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: Offset(0, 2),
),
],
),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
radius: 16,
backgroundColor: Color(0xFF6A4C93),
child: Text(
(userData!['displayName'] ?? 'U').substring(0, 1).toUpperCase(),
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
userData!['displayName'] ?? 'Unknown User',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14,
color: Colors.black87,
),
),
Text(
post['timestamp'],
style: TextStyle(
color: Colors.grey[600],
fontSize: 12,
),
),
],
),
),
],
),
SizedBox(height: 12),
Text(
post['content'],
style: TextStyle(
fontSize: 15,
height: 1.4,
color: Colors.black87,
),
),
SizedBox(height: 12),
Row(
children: [
Icon(
post['isLiked']
? Icons.favorite
: Icons.favorite_border,
color: post['isLiked']
? Colors.red
: Colors.grey[600],
size: 20,
),
SizedBox(width: 4),
Text(
'${post['likes']}',
style: TextStyle(
color: Colors.grey[700],
fontSize: 14,
),
),
SizedBox(width: 16),
Icon(
Icons.chat_bubble_outline,
color: Colors.grey[600],
size: 20,
),
SizedBox(width: 4),
Text(
'${post['comments']}',
style: TextStyle(
color: Colors.grey[700],
fontSize: 14,
),
),
],
),
],
),
),
);
},
),
],
SizedBox(height: 24),
],
),
@ -525,4 +598,4 @@ class _SettingsPageState extends State<SettingsPage> {
),
);
}
}
}

View File

@ -0,0 +1,72 @@
import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import '../constants/api_constants.dart';
class AuthService {
static const FlutterSecureStorage _storage = FlutterSecureStorage();
static const String _tokenKey = 'jwt_token';
static Future<Map<String, dynamic>> login(
String emailOrUsername,
String password,
) async {
try {
final response = await http.post(
Uri.parse('${ApiConstants.baseUrl}${ApiConstants.loginEndpoint}'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'emailOrUsername': emailOrUsername,
'password': password,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final token = data['token'];
if (token != null) {
await _storage.write(key: _tokenKey, value: token);
return {'success': true};
}
return {'success': false, 'message': 'No token received'};
} else if (response.statusCode == 403 || response.statusCode == 400) {
return {'success': false, 'message': 'Invalid credentials'};
} else if (response.statusCode == 401) {
return {'success': false, 'message': 'Invalid credentials'};
} else {
return {
'success': false,
'message': 'Server error (${response.statusCode})',
};
}
} catch (e) {
print('Login error: $e');
return {
'success': false,
'message': 'Network error. Please check your connection.',
};
}
}
static Future<String?> getToken() async {
return await _storage.read(key: _tokenKey);
}
static Future<bool> isLoggedIn() async {
final token = await getToken();
return token != null && token.isNotEmpty;
}
static Future<void> logout() async {
await _storage.delete(key: _tokenKey);
}
static Future<Map<String, String>> getAuthHeaders() async {
final token = await getToken();
return {
'Content-Type': 'application/json',
if (token != null) 'Authorization': 'Bearer $token',
};
}
}

View File

@ -0,0 +1,40 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../constants/api_constants.dart';
import 'auth_service.dart';
class HttpService {
static Future<http.Response> get(String endpoint) async {
final headers = await AuthService.getAuthHeaders();
return await http.get(
Uri.parse('${ApiConstants.baseUrl}$endpoint'),
headers: headers,
);
}
static Future<http.Response> post(String endpoint, Map<String, dynamic> body) async {
final headers = await AuthService.getAuthHeaders();
return await http.post(
Uri.parse('${ApiConstants.baseUrl}$endpoint'),
headers: headers,
body: jsonEncode(body),
);
}
static Future<http.Response> put(String endpoint, Map<String, dynamic> body) async {
final headers = await AuthService.getAuthHeaders();
return await http.put(
Uri.parse('${ApiConstants.baseUrl}$endpoint'),
headers: headers,
body: jsonEncode(body),
);
}
static Future<http.Response> delete(String endpoint) async {
final headers = await AuthService.getAuthHeaders();
return await http.delete(
Uri.parse('${ApiConstants.baseUrl}$endpoint'),
headers: headers,
);
}
}

View File

@ -0,0 +1,25 @@
import 'dart:convert';
import '../constants/api_constants.dart';
import 'http_service.dart';
class UserService {
static Future<Map<String, dynamic>> getCurrentUser() async {
try {
final response = await HttpService.get(ApiConstants.getUserEndpoint);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return {'success': true, 'data': data};
} else if (response.statusCode == 401) {
return {'success': false, 'message': 'Session expired. Please login again.'};
} else if (response.statusCode == 403) {
return {'success': false, 'message': 'Access denied. Invalid credentials.'};
} else {
return {'success': false, 'message': 'Server error (${response.statusCode})'};
}
} catch (e) {
print('Error fetching user: $e');
return {'success': false, 'message': 'Network error. Please check your connection.'};
}
}
}

View File

@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h"
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
}

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@ -7,8 +7,12 @@ import Foundation
import firebase_core
import firebase_messaging
import flutter_secure_storage_macos
import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
}

View File

@ -81,6 +81,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.3"
ffi:
dependency: transitive
description:
name: ffi
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
firebase_core:
dependency: "direct main"
description:
@ -142,6 +150,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.0"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
url: "https://pub.dev"
source: hosted
version: "9.2.4"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688
url: "https://pub.dev"
source: hosted
version: "1.2.3"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
url: "https://pub.dev"
source: hosted
version: "1.2.1"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_test:
dependency: "direct dev"
description: flutter
@ -184,6 +240,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.1.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
leak_tracker:
dependency: transitive
description:
@ -248,6 +312,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
url: "https://pub.dev"
source: hosted
version: "2.1.5"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
url: "https://pub.dev"
source: hosted
version: "2.2.17"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev"
source: hosted
version: "2.3.0"
platform:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.dev"
source: hosted
version: "3.1.6"
plugin_platform_interface:
dependency: transitive
description:
@ -341,6 +461,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.1"
win32:
dependency: transitive
description:
name: win32
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03"
url: "https://pub.dev"
source: hosted
version: "5.14.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
sdks:
dart: ">=3.8.1 <4.0.0"
flutter: ">=3.22.0"
flutter: ">=3.27.0"

View File

@ -14,6 +14,7 @@ dependencies:
firebase_messaging: ^15.2.9
http: ^1.1.0
googleapis_auth: ^1.6.0
flutter_secure_storage: ^9.2.2
dev_dependencies:
flutter_test:

View File

@ -7,8 +7,11 @@
#include "generated_plugin_registrant.h"
#include <firebase_core/firebase_core_plugin_c_api.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FirebaseCorePluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
}

View File

@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
firebase_core
flutter_secure_storage_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST