Modified build.yaml, added logo, made profile screen float
All checks were successful
Build Flutter Web and Docker Image for Local Registry / Build Flutter Web App (push) Successful in 3m7s

This commit is contained in:
whysman 2024-11-09 22:50:56 -05:00
parent 2817b75f2e
commit 996c294153
8 changed files with 141 additions and 80 deletions

View File

@ -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
docker push localhost:5000/pogdark-app:latest

View File

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 167 KiB

BIN
assets/pogdark_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

View File

@ -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<MyApp> {
Future<void>? _prefsReady;
bool isProfileActive = false;
bool showProfileInitially = false;
@override
void initState() {
super.initState();
_prefsReady =
Provider.of<SharedPreferencesProvider>(context, listen: false).ready;
_prefsReady!.then((_) {
final prefsProvider =
Provider.of<SharedPreferencesProvider>(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<MyApp> {
future: _prefsReady,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (Provider.of<SharedPreferencesProvider>(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());
}

View File

@ -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<ProfileScreen> {
final TextEditingController _nameController = TextEditingController();
late String? imageData;
bool isNameEmpty = true;
final ImagePicker _picker = ImagePicker();
@override
@ -31,6 +33,16 @@ class ProfileScreenState extends State<ProfileScreen> {
Provider.of<SharedPreferencesProvider>(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<void> _pickImage() async {
@ -62,13 +74,8 @@ class ProfileScreenState extends State<ProfileScreen> {
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<ProfileScreen> {
}
}
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<ProfileScreen> {
final prefsProvider = Provider.of<SharedPreferencesProvider>(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'),
),
],
),
),
),
);

View File

@ -16,7 +16,8 @@ class SharedPreferencesProvider extends ChangeNotifier {
Future<void> _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<int> imageBytes = bytes.buffer.asUint8List();
prefs.setString('userLogo', base64Encode(imageBytes));
prefs.setString('id', const Uuid().v4());

View File

@ -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<StatusPage> {
Uri.parse('wss://api.pogdark.com:8889/ws'),
);
// Convert the stream to a broadcast stream
late final Stream<dynamic> broadcastStream;
late StreamController<dynamic> controller;
List<Map<String, dynamic>> messages =
[]; // To hold user messages with names and timestamps
List<Map<String, dynamic>> messages = []; // To hold user messages
@override
void initState() {
@ -39,14 +38,6 @@ class StatusPageState extends State<StatusPage> {
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<StatusPage> {
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<StatusPage> {
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<StatusPage> {
final newMessage =
jsonDecode(snapshot.data as String) as Map<String, dynamic>;
// 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<StatusPage> {
Expanded(
child: Row(
children: [
// Column for "On the way" messages
Expanded(
child: Column(
children: [
@ -169,7 +160,6 @@ class StatusPageState extends State<StatusPage> {
],
),
),
// Column for "Arrived" messages
Expanded(
child: Column(
children: [

View File

@ -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