commit 104ce305cb45402a93618fb018309a439294d0df
parent a7a2ef91001d50bf7cbca0e114b4f5ad8b907ff3
Author: maydayv7 <maydayv7@gmail.com>
Date: Sat, 6 Dec 2025 05:30:26 +0530
Add setting for user name
Diffstat:
7 files changed, 207 insertions(+), 51 deletions(-)
diff --git a/lib/ui/pages/canvas_page.dart b/lib/ui/pages/canvas_page.dart
@@ -1605,7 +1605,7 @@ class _CanvasPageState extends State<CanvasPage> {
debugPrint("Generation Error: $e");
ScaffoldMessenger.of(
context,
- ).showSnackBar(const SnackBar(content: Text("Generation failed.")));
+ ).showSnackBar(const SnackBar(content: Text("Generation failed")));
} finally {
setState(() {
_isInpainting = false;
diff --git a/lib/ui/pages/define_brand_page.dart b/lib/ui/pages/define_brand_page.dart
@@ -61,7 +61,7 @@ class _DefineBrandPageState extends State<DefineBrandPage> {
// 1. Basic Validation
if (_projectNameController.text.trim().isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(content: Text('Project name is required.')),
+ const SnackBar(content: Text('Project name is required')),
);
return;
}
diff --git a/lib/ui/pages/home_page.dart b/lib/ui/pages/home_page.dart
@@ -2,6 +2,7 @@ import 'dart:io';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
+import 'package:shared_preferences/shared_preferences.dart';
import 'package:creekui/data/models/project_model.dart';
import 'package:creekui/data/models/file_model.dart';
import 'package:creekui/data/repos/project_repo.dart';
@@ -14,6 +15,7 @@ import 'package:creekui/ui/widgets/file_card.dart';
import 'package:creekui/ui/widgets/project_card.dart';
import 'package:creekui/ui/widgets/empty_state.dart';
import 'package:creekui/ui/widgets/section_header.dart';
+import 'package:creekui/ui/pages/settings_page.dart';
import 'project_detail_page.dart';
import 'define_brand_page.dart';
import 'canvas_page.dart';
@@ -40,7 +42,7 @@ class _HomePageState extends State<HomePage> {
final Map<int, List<String>> _projectPreviews = {};
Map<String, Map<String, String>> _fileMetadata = {};
bool _isLoading = true;
- final String _userName = "Alex"; // TODO
+ String _userName = "Alex"; // Default
@override
void initState() {
@@ -57,6 +59,10 @@ class _HomePageState extends State<HomePage> {
Future<void> _loadData() async {
setState(() => _isLoading = true);
try {
+ // Load User Name
+ final prefs = await SharedPreferences.getInstance();
+ final storedName = prefs.getString('user_name') ?? "Alex";
+
final allProjects = await _projectRepo.getAllProjects();
final Map<int, ProjectModel> projectMap = {};
for (final project in allProjects) {
@@ -114,6 +120,7 @@ class _HomePageState extends State<HomePage> {
if (mounted) {
setState(() {
+ _userName = storedName;
_allProjects = allProjects;
_recentFiles = recentFiles;
_projectMap = projectMap;
@@ -470,21 +477,34 @@ class _HomePageState extends State<HomePage> {
),
),
const Spacer(),
- Container(
- width: 30,
- height: 30,
- decoration: BoxDecoration(
- color: theme.colorScheme.primaryContainer,
- shape: BoxShape.circle,
- border: Border.all(
- color: theme.scaffoldBackgroundColor,
- width: 1.25,
+ GestureDetector(
+ onTap: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (_) => const SettingsPage(),
+ ),
+ ).then((_) {
+ _loadData(); // Reload to update name
+ });
+ },
+ behavior: HitTestBehavior.opaque,
+ child: Container(
+ width: 30,
+ height: 30,
+ decoration: BoxDecoration(
+ color: theme.colorScheme.primaryContainer,
+ shape: BoxShape.circle,
+ border: Border.all(
+ color: theme.scaffoldBackgroundColor,
+ width: 1.25,
+ ),
+ ),
+ child: Icon(
+ Icons.person,
+ size: 16,
+ color: theme.colorScheme.onPrimaryContainer,
),
- ),
- child: Icon(
- Icons.person,
- size: 16,
- color: theme.colorScheme.onPrimaryContainer,
),
),
],
diff --git a/lib/ui/pages/settings_page.dart b/lib/ui/pages/settings_page.dart
@@ -1,12 +1,66 @@
import 'package:flutter/material.dart';
+import 'package:shared_preferences/shared_preferences.dart';
import 'package:creekui/ui/styles/variables.dart';
import 'package:creekui/ui/pages/image_analysis_page.dart';
+import 'package:creekui/ui/widgets/primary_button.dart';
-class SettingsPage extends StatelessWidget {
+class SettingsPage extends StatefulWidget {
const SettingsPage({super.key});
@override
+ State<SettingsPage> createState() => _SettingsPageState();
+}
+
+class _SettingsPageState extends State<SettingsPage> {
+ final TextEditingController _nameController = TextEditingController();
+ bool _isLoading = true;
+ String _originalName = '';
+
+ @override
+ void initState() {
+ super.initState();
+ _loadUserData();
+ }
+
+ Future<void> _loadUserData() async {
+ final prefs = await SharedPreferences.getInstance();
+ String name = prefs.getString('user_name') ?? 'Alex';
+ if (name.trim().isEmpty) {
+ name = 'Alex';
+ }
+
+ setState(() {
+ _nameController.text = name;
+ _originalName = name;
+ _isLoading = false;
+ });
+ }
+
+ Future<void> _saveUserName() async {
+ final newName = _nameController.text.trim();
+ if (newName.isEmpty) return;
+
+ final prefs = await SharedPreferences.getInstance();
+ await prefs.setString('user_name', newName);
+
+ setState(() {
+ _originalName = newName;
+ });
+
+ if (mounted) {
+ FocusScope.of(context).unfocus();
+ }
+ }
+
+ @override
+ void dispose() {
+ _nameController.dispose();
+ super.dispose();
+ }
+
+ @override
Widget build(BuildContext context) {
+ final bool hasChanges = _nameController.text.trim() != _originalName;
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
@@ -21,29 +75,94 @@ class SettingsPage extends StatelessWidget {
elevation: 0,
iconTheme: const IconThemeData(color: Variables.textPrimary),
),
- body: ListView(
- children: [
- ListTile(
- title: const Text(
- "Test Image Analysis",
- style: TextStyle(
- fontFamily: 'GeneralSans',
- color: Variables.textPrimary,
+ body:
+ _isLoading
+ ? const Center(child: CircularProgressIndicator())
+ : Padding(
+ padding: const EdgeInsets.all(24.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const Text(
+ "Profile Settings",
+ style: TextStyle(
+ fontFamily: 'GeneralSans',
+ fontSize: 18,
+ fontWeight: FontWeight.w600,
+ color: Variables.textPrimary,
+ ),
+ ),
+ const SizedBox(height: 16),
+
+ // User Name Field
+ const Text(
+ "Your Name",
+ style: TextStyle(
+ fontFamily: 'GeneralSans',
+ fontSize: 14,
+ color: Variables.textSecondary,
+ ),
+ ),
+ const SizedBox(height: 8),
+ TextField(
+ controller: _nameController,
+ onChanged: (val) {
+ setState(
+ () {},
+ ); // Trigger rebuild to show/hide checkmark
+ },
+ decoration: InputDecoration(
+ hintText: "Enter your name",
+ hintStyle: TextStyle(
+ color: Variables.textSecondary.withValues(alpha: 0.5),
+ ),
+ filled: true,
+ fillColor: Variables.surfaceSubtle,
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(12),
+ borderSide: BorderSide.none,
+ ),
+ contentPadding: const EdgeInsets.symmetric(
+ horizontal: 16,
+ vertical: 12,
+ ),
+ suffixIcon:
+ hasChanges
+ ? IconButton(
+ icon: const Icon(
+ Icons.check,
+ color: Variables.textPrimary,
+ ),
+ onPressed: _saveUserName,
+ tooltip: 'Save Name',
+ )
+ : null,
+ ),
+ style: const TextStyle(
+ fontFamily: 'GeneralSans',
+ fontSize: 16,
+ color: Variables.textPrimary,
+ ),
+ ),
+
+ const Spacer(),
+
+ // Test Analysis
+ PrimaryButton(
+ text: "Test Image Analysis",
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (_) => const ImageAnalysisPage(),
+ ),
+ );
+ },
+ ),
+ const SizedBox(height: 20),
+ ],
+ ),
),
- ),
- trailing: const Icon(
- Icons.chevron_right,
- color: Variables.textSecondary,
- ),
- onTap: () {
- Navigator.push(
- context,
- MaterialPageRoute(builder: (_) => const ImageAnalysisPage()),
- );
- },
- ),
- ],
- ),
);
}
}
diff --git a/lib/ui/pages/stylesheet_page.dart b/lib/ui/pages/stylesheet_page.dart
@@ -178,7 +178,7 @@ class _StylesheetPageState extends State<StylesheetPage> {
if (analysisData.isEmpty) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(content: Text("No analyzed images or notes found.")),
+ const SnackBar(content: Text("No analyzed images or notes found")),
);
}
return;
diff --git a/lib/ui/widgets/note_input_sheet.dart b/lib/ui/widgets/note_input_sheet.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:shared_preferences/shared_preferences.dart';
import 'package:creekui/ui/styles/variables.dart';
class NoteInputSheet extends StatefulWidget {
@@ -20,11 +21,22 @@ class NoteInputSheet extends StatefulWidget {
class _NoteInputSheetState extends State<NoteInputSheet> {
late String _selectedCategory;
final TextEditingController _controller = TextEditingController();
+ String _userName = "Alex"; // Default
@override
void initState() {
super.initState();
_selectedCategory = widget.initialCategory;
+ _loadUserName();
+ }
+
+ Future<void> _loadUserName() async {
+ final prefs = await SharedPreferences.getInstance();
+ if (mounted) {
+ setState(() {
+ _userName = prefs.getString('user_name') ?? "Alex";
+ });
+ }
}
@override
@@ -60,9 +72,9 @@ class _NoteInputSheetState extends State<NoteInputSheet> {
),
),
const SizedBox(width: 10),
- const Text(
- "Alex", // TODO
- style: TextStyle(
+ Text(
+ _userName,
+ style: const TextStyle(
fontFamily: 'GeneralSans',
fontSize: 12,
fontWeight: FontWeight.w500,
diff --git a/lib/ui/widgets/top_bar.dart b/lib/ui/widgets/top_bar.dart
@@ -150,6 +150,7 @@ class _TopBarState extends State<TopBar> {
// Back Button
GestureDetector(
onTap: _handleSafeBack,
+ behavior: HitTestBehavior.opaque,
child: Container(
width: 24,
height: 24,
@@ -198,13 +199,17 @@ class _TopBarState extends State<TopBar> {
if (!widget.hideSecondRow)
GestureDetector(
onTap: _openSettings,
- child: SvgPicture.asset(
- 'assets/icons/settings-line.svg',
- width: 24,
- height: 24,
- colorFilter: const ColorFilter.mode(
- Variables.textPrimary,
- BlendMode.srcIn,
+ behavior: HitTestBehavior.opaque,
+ child: Container(
+ padding: const EdgeInsets.all(4),
+ child: SvgPicture.asset(
+ 'assets/icons/settings-line.svg',
+ width: 24,
+ height: 24,
+ colorFilter: const ColorFilter.mode(
+ Variables.textPrimary,
+ BlendMode.srcIn,
+ ),
),
),
),