From efefb1c34b50c000985b73335a5f9f567644f3d1 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Thu, 20 Nov 2025 17:19:48 +0530 Subject: [PATCH] feat: add app version display to user profile bar and update version number in pubspec.yaml --- lib/view/layouts/user_profile_right_bar.dart | 194 ++++++++++++++----- pubspec.yaml | 2 +- 2 files changed, 149 insertions(+), 47 deletions(-) diff --git a/lib/view/layouts/user_profile_right_bar.dart b/lib/view/layouts/user_profile_right_bar.dart index 2ef33ba..a36a555 100644 --- a/lib/view/layouts/user_profile_right_bar.dart +++ b/lib/view/layouts/user_profile_right_bar.dart @@ -2,6 +2,7 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_lucide/flutter_lucide.dart'; import 'package:get/get.dart'; +import 'package:package_info_plus/package_info_plus.dart'; import 'package:marco/helpers/services/storage/local_storage.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; @@ -15,7 +16,6 @@ import 'package:marco/view/tenant/tenant_selection_screen.dart'; import 'package:marco/controller/tenant/tenant_switch_controller.dart'; import 'package:marco/helpers/theme/theme_editor_widget.dart'; - class UserProfileBar extends StatefulWidget { final bool isCondensed; const UserProfileBar({Key? key, this.isCondensed = false}) : super(key: key); @@ -30,6 +30,7 @@ class _UserProfileBarState extends State bool _isLoading = true; bool hasMpin = true; bool _isThemeEditorVisible = false; + String _appVersion = ''; @override void initState() { @@ -40,6 +41,11 @@ class _UserProfileBarState extends State Future _initData() async { employeeInfo = LocalStorage.getEmployeeInfo()!; hasMpin = await LocalStorage.getIsMpin(); + + // Fetch app version + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + _appVersion = '${packageInfo.version}+${packageInfo.buildNumber}'; + setState(() => _isLoading = false); } @@ -79,55 +85,155 @@ class _UserProfileBarState extends State ), ), child: SafeArea( - bottom: true, - child: Stack( - children: [ - Offstage( - offstage: _isThemeEditorVisible, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _isLoading - ? const _LoadingSection() - : _userProfileSection(isCondensed), - if (!_isLoading && !isCondensed) _switchTenantRow(), - MySpacing.height(12), - Divider( - indent: 18, - endIndent: 18, - thickness: 0.7, - color: Colors.grey.withOpacity(0.25), - ), - MySpacing.height(12), - _supportAndSettingsMenu(isCondensed), - const Spacer(), - Divider( - indent: 18, - endIndent: 18, - thickness: 0.35, - color: Colors.grey.withOpacity(0.18), - ), - _logoutButton(isCondensed), - ], - ), + bottom: true, + child: Stack( + children: [ + Offstage( + offstage: _isThemeEditorVisible, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _isLoading + ? const _LoadingSection() + : _userProfileSection(isCondensed), + if (!_isLoading && !isCondensed) _switchTenantRow(), + MySpacing.height(12), + Divider( + indent: 18, + endIndent: 18, + thickness: 0.7, + color: Colors.grey.withOpacity(0.25), + ), + MySpacing.height(12), + _supportAndSettingsMenu(isCondensed), + MySpacing.height(12), + + // Subtle version text for expanded mode + if (!isCondensed && _appVersion.isNotEmpty) + _versionText(), + + const Spacer(), + Divider( + indent: 18, + endIndent: 18, + thickness: 0.35, + color: Colors.grey.withOpacity(0.18), + ), + _logoutButton(isCondensed), + ], ), - Offstage( - offstage: !_isThemeEditorVisible, - child: ThemeEditorWidget( - onClose: () { - setState(() => _isThemeEditorVisible = false); - }, - ), + ), + Offstage( + offstage: !_isThemeEditorVisible, + child: ThemeEditorWidget( + onClose: () { + setState(() => _isThemeEditorVisible = false); + }, ), - ], - )), + ), + + // Floating badge for condensed mode + if (isCondensed && _appVersion.isNotEmpty) _versionBadge(), + ], + ), + ), ), ), ), ); } - // ==================== CONTINUE EXISTING CODE ===================== + // =================== Version Widgets =================== + + Widget _versionText() { + return Padding( + padding: const EdgeInsets.only(top: 4, bottom: 12), + child: Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6), + decoration: BoxDecoration( + color: Colors.grey.shade100.withOpacity(0.85), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Colors.grey.shade200, + width: 0.7, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.12), + blurRadius: 3, + offset: const Offset(0, 1), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.info_outline, size: 14, color: Colors.grey[700]), + const SizedBox(width: 4), + Text( + 'Version: $_appVersion', + style: TextStyle( + fontSize: 12, + color: Colors.grey[800], + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + ), + ), + ); + } + + Widget _versionBadge() { + return Positioned( + bottom: 10, + right: 14, + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), + decoration: BoxDecoration( + color: Colors.grey.shade100.withOpacity(0.85), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Colors.grey.shade300, + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.17), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Text( + _appVersion, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Colors.black87, + letterSpacing: 0.4, + ), + ), + ), + ), + ), + ); + } + + // =================== Existing methods =================== + Widget _switchTenantRow() { final TenantSwitchController tenantSwitchController = Get.put(TenantSwitchController()); @@ -443,24 +549,20 @@ class _UserProfileBarState extends State child: Column( mainAxisSize: MainAxisSize.min, children: [ - // Top icon Icon(LucideIcons.log_out, size: 56, color: primaryColor), MySpacing.height(18), - // Title MyText.titleLarge( "Logout Confirmation", fontWeight: 700, textAlign: TextAlign.center, ), MySpacing.height(14), - // Subtitle MyText.bodyMedium( "Are you sure you want to logout?\nYou will need to login again to continue.", color: Colors.grey[700], textAlign: TextAlign.center, ), MySpacing.height(30), - // Buttons Row( children: [ Expanded( diff --git a/pubspec.yaml b/pubspec.yaml index 196d3da..aa6af1f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+14 +version: 1.0.0+15 environment: sdk: ^3.5.3