diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index bece778..e980e00 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -44,8 +44,8 @@ jobs: - name: Build Docker Image run: | - docker build -t localhost:5000/pogdark:latest . + docker build -t localhost:5000/pogdark-app:latest . - name: Push Docker Image to Local Registry run: | - docker push localhost:5000/pogdark:latest \ No newline at end of file + docker push localhost:5000/pogdark-app:latest \ No newline at end of file diff --git a/assets/default_logo.png b/assets/default_profile_image.png similarity index 100% rename from assets/default_logo.png rename to assets/default_profile_image.png diff --git a/assets/pogdark_logo.png b/assets/pogdark_logo.png new file mode 100644 index 0000000..0b6f929 Binary files /dev/null and b/assets/pogdark_logo.png differ diff --git a/lib/main.dart b/lib/main.dart index 4e1ec3c..f56fd48 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -25,12 +26,36 @@ class MyApp extends StatefulWidget { class MyAppState extends State { Future? _prefsReady; + bool isProfileActive = false; + bool showProfileInitially = false; @override void initState() { super.initState(); _prefsReady = Provider.of(context, listen: false).ready; + _prefsReady!.then((_) { + final prefsProvider = + Provider.of(context, listen: false); + // Check if username is not set; if so, show ProfileScreen initially + if (prefsProvider.getUserName().isEmpty) { + setState(() { + showProfileInitially = true; + }); + } + }); + } + + void toggleProfileScreen() { + setState(() { + isProfileActive = !isProfileActive; + }); + } + + void closeInitialProfileScreen() { + setState(() { + showProfileInitially = false; + }); } @override @@ -53,12 +78,38 @@ class MyAppState extends State { future: _prefsReady, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - if (Provider.of(context).getUserName() != - '') { - return const StatusPage(); - } else { - return const ProfileScreen(isEditing: false); - } + return Stack( + children: [ + StatusPage(toggleProfile: toggleProfileScreen), + if (showProfileInitially) + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: Container( + color: Colors.black.withOpacity(0.3), + child: Center( + child: ProfileScreen( + isEditing: false, + onClose: + closeInitialProfileScreen, // Close after setup + ), + ), + ), + ), + if (isProfileActive && !showProfileInitially) + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: Container( + color: Colors.black.withOpacity(0.3), + child: Center( + child: ProfileScreen( + isEditing: true, + onClose: toggleProfileScreen, // Toggle on edit + ), + ), + ), + ), + ], + ); } else { return const Center(child: CircularProgressIndicator()); } diff --git a/lib/profile_screen.dart b/lib/profile_screen.dart index 1685a83..f965130 100644 --- a/lib/profile_screen.dart +++ b/lib/profile_screen.dart @@ -8,12 +8,13 @@ import 'package:image_picker/image_picker.dart'; import 'package:provider/provider.dart'; import 'shared_preferences_provider.dart'; -import 'status_page.dart'; class ProfileScreen extends StatefulWidget { final bool isEditing; + final VoidCallback onClose; - const ProfileScreen({super.key, required this.isEditing}); + const ProfileScreen( + {super.key, required this.isEditing, required this.onClose}); @override ProfileScreenState createState() => ProfileScreenState(); @@ -22,6 +23,7 @@ class ProfileScreen extends StatefulWidget { class ProfileScreenState extends State { final TextEditingController _nameController = TextEditingController(); late String? imageData; + bool isNameEmpty = true; final ImagePicker _picker = ImagePicker(); @override @@ -31,6 +33,16 @@ class ProfileScreenState extends State { Provider.of(context, listen: false); _nameController.text = prefsProvider.getUserName(); imageData = prefsProvider.getUserLogo(); + + // Check initial state of the name field and add listener + _nameController.addListener(_checkNameField); + isNameEmpty = _nameController.text.trim().isEmpty; + } + + void _checkNameField() { + setState(() { + isNameEmpty = _nameController.text.trim().isEmpty; + }); } Future _pickImage() async { @@ -62,13 +74,8 @@ class ProfileScreenState extends State { await prefsProvider.setUserName(name); await prefsProvider.setUserLogo(imageData); - if (widget.isEditing) { - if (mounted) { - Navigator.pop(context); // Go back to the Status screen if editing - } - } else { - _navigateToStatusScreen(); // Go to Status screen if this is the initial entry - } + // Close the screen after saving if the name is valid + widget.onClose(); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Name cannot be empty!')), @@ -77,15 +84,9 @@ class ProfileScreenState extends State { } } - void _navigateToStatusScreen() { - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => const StatusPage()), - ); - } - @override void dispose() { + _nameController.removeListener(_checkNameField); _nameController.dispose(); super.dispose(); } @@ -103,43 +104,60 @@ class ProfileScreenState extends State { final prefsProvider = Provider.of(context); final userLogo = prefsProvider.getUserLogo(); - return Scaffold( - appBar: AppBar( - title: Text( - widget.isEditing ? 'Edit Profile' : 'Enter Your Name and Logo'), - backgroundColor: Colors.blueAccent, - ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Profile Image Display - Center( - child: CircleAvatar( + return Center( + child: Material( + color: Colors.white, + borderRadius: BorderRadius.circular(20.0), + elevation: 10.0, + child: Container( + width: MediaQuery.of(context).size.width * 0.8, + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Align( + alignment: Alignment.topRight, + child: IconButton( + icon: const Icon(Icons.close), + onPressed: isNameEmpty ? null : widget.onClose, + color: isNameEmpty ? Colors.grey : Colors.black, + ), + ), + Text( + widget.isEditing + ? 'Edit Your Information' + : 'Tell Us About Yourself', + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + CircleAvatar( radius: 50, backgroundImage: getLogoImage(userLogo).image, ), - ), - const SizedBox(height: 20), - TextField( - controller: _nameController, - decoration: const InputDecoration( - labelText: 'Name', - border: OutlineInputBorder(), + const SizedBox(height: 20), + TextField( + controller: _nameController, + decoration: const InputDecoration( + labelText: 'Your Pet\'s Name', + border: OutlineInputBorder(), + ), ), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: _pickImage, - child: const Text('Upload Logo'), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: _saveProfile, - child: Text(widget.isEditing ? 'Save Changes' : 'Continue'), - ), - ], + const SizedBox(height: 20), + ElevatedButton( + onPressed: _pickImage, + child: const Text('Upload Profile Image'), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: _saveProfile, + child: Text(widget.isEditing ? 'Save Changes' : 'Continue'), + ), + ], + ), ), ), ); diff --git a/lib/shared_preferences_provider.dart b/lib/shared_preferences_provider.dart index 90d7b99..6a2ee19 100644 --- a/lib/shared_preferences_provider.dart +++ b/lib/shared_preferences_provider.dart @@ -16,7 +16,8 @@ class SharedPreferencesProvider extends ChangeNotifier { Future _initPrefs() async { prefs = await SharedPreferences.getInstance(); if (prefs.getString('userLogo') == null) { - ByteData bytes = await rootBundle.load('assets/default_logo.png'); + ByteData bytes = + await rootBundle.load('assets/default_profile_image.png'); List imageBytes = bytes.buffer.asUint8List(); prefs.setString('userLogo', base64Encode(imageBytes)); prefs.setString('id', const Uuid().v4()); diff --git a/lib/status_page.dart b/lib/status_page.dart index d8452f2..2ec3477 100644 --- a/lib/status_page.dart +++ b/lib/status_page.dart @@ -5,11 +5,12 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; -import 'profile_screen.dart'; import 'shared_preferences_provider.dart'; class StatusPage extends StatefulWidget { - const StatusPage({super.key}); + final VoidCallback toggleProfile; + + const StatusPage({super.key, required this.toggleProfile}); @override StatusPageState createState() => StatusPageState(); @@ -20,12 +21,10 @@ class StatusPageState extends State { Uri.parse('wss://api.pogdark.com:8889/ws'), ); - // Convert the stream to a broadcast stream late final Stream broadcastStream; late StreamController controller; - List> messages = - []; // To hold user messages with names and timestamps + List> messages = []; // To hold user messages @override void initState() { @@ -39,14 +38,6 @@ class StatusPageState extends State { return messages.where((message) => message['Status'] == status).toList(); } - void _navigateToEditProfile() { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const ProfileScreen(isEditing: true)), - ); - } - void _sendStatus(String id, String name, String? image, String status) { final message = jsonEncode({ 'Id': id, @@ -81,7 +72,7 @@ class StatusPageState extends State { radius: 20, backgroundImage: message['Image'] != null ? Image.memory(base64Decode(message['Image'])).image - : const AssetImage('assets/default_logo.png'), + : const AssetImage('assets/default_profile_image.png'), ), const SizedBox(width: 8), Text( @@ -112,12 +103,15 @@ class StatusPageState extends State { return Scaffold( appBar: AppBar( - title: const Text('Pogdark'), + title: Image.asset( + 'assets/pogdark_logo.png', + height: 40, + ), backgroundColor: Colors.blueAccent, actions: [ IconButton( icon: const Icon(Icons.edit), - onPressed: _navigateToEditProfile, + onPressed: widget.toggleProfile, // Open ProfileScreen overlay ), ], ), @@ -128,16 +122,14 @@ class StatusPageState extends State { final newMessage = jsonDecode(snapshot.data as String) as Map; - // Update messages only if new or modified final incomingId = newMessage['Id']; messages.removeWhere((msg) => msg['Id'] == incomingId); - if (newMessage['Status'] != 'expired' || + if (newMessage['Status'] != 'expired' && newMessage['Status'] != "is leaving") { messages.add(newMessage); } } - // Separate messages by status final onTheWayMessages = _getMessagesByStatus('is on the way'); final arrivedMessages = _getMessagesByStatus('has arrived'); @@ -148,7 +140,6 @@ class StatusPageState extends State { Expanded( child: Row( children: [ - // Column for "On the way" messages Expanded( child: Column( children: [ @@ -169,7 +160,6 @@ class StatusPageState extends State { ], ), ), - // Column for "Arrived" messages Expanded( child: Column( children: [ diff --git a/pubspec.yaml b/pubspec.yaml index 7a437f3..6b39afc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,7 +70,8 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - - assets/default_logo.png + - assets/default_profile_image.png + - assets/pogdark_logo.png # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg