This commit is contained in:
2026-06-21 14:45:30 +03:00
parent 127a917eac
commit 3961327bdb
16 changed files with 852 additions and 396 deletions
@@ -2,6 +2,7 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../core/constants.dart';
import '../../../../core/utils/card_layout.dart';
import '../../../../shared/models/account.dart';
import '../../../../shared/models/transaction.dart';
import '../../../../shared/widgets/byn_sign.dart';
@@ -84,12 +85,13 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
@override
Widget build(BuildContext context) {
final mq = MediaQuery.of(widget.context);
final cardTop = mq.padding.top + kToolbarHeight + 16;
const cardHeight = 190.0;
const editorPanelHeight = 102.0;
final editorPanelTop = cardTop + cardHeight + 20;
final colorPanelTop = editorPanelTop + editorPanelHeight + 12;
const colorPanelHeight = 410.0;
final layout = CardOverlayLayout.fromMediaQuery(mq);
final cardTop = layout.cardTop;
final cardHeight = layout.cardHeight;
final editorPanelHeight = layout.editorPanelHeight;
final editorPanelTop = cardTop + cardHeight + layout.sectionGap;
final colorPanelTop = editorPanelTop + editorPanelHeight + layout.sectionGap;
final colorPanelHeight = layout.colorPanelHeight(mq, colorPanelTop);
return Consumer(
builder: (context, ref, _) {
@@ -263,6 +265,7 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
dashboardState: dash,
dashboardContext: widget.context,
panelHeight: colorPanelHeight,
layout: layout,
isDuplicateName: _isDuplicateName,
onDuplicateError: () {
setState(() => _showDuplicateError = true);
@@ -5,6 +5,7 @@ import '../../../../core/l10n/app_strings.dart';
import '../../../../core/l10n/locale_provider.dart';
import '../../../../core/services/card_color_service.dart';
import '../../../../core/services/haptic_service.dart';
import '../../../../core/utils/card_layout.dart';
import '../../../../shared/models/account.dart';
import '../../provider.dart';
import './panel_tab.dart';
@@ -14,6 +15,7 @@ class AccountColorPanel extends StatelessWidget {
final dynamic dashboardState;
final BuildContext dashboardContext;
final double panelHeight;
final CardOverlayLayout layout;
final bool Function(List<Account>, String) isDuplicateName;
final VoidCallback onDuplicateError;
@@ -22,6 +24,7 @@ class AccountColorPanel extends StatelessWidget {
required this.dashboardState,
required this.dashboardContext,
required this.panelHeight,
required this.layout,
required this.isDuplicateName,
required this.onDuplicateError,
});
@@ -77,7 +80,12 @@ class AccountColorPanel extends StatelessWidget {
: dashboardState.tempSecondaryHSV;
return Padding(
padding: const EdgeInsets.fromLTRB(16, 14, 16, 22),
padding: EdgeInsets.fromLTRB(
16,
layout.panelPaddingTop,
16,
layout.panelPaddingBottom,
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -239,12 +247,12 @@ class AccountColorPanel extends StatelessWidget {
],
),
),
const SizedBox(height: 10),
SizedBox(height: layout.tabSpacing),
Expanded(
child: LayoutBuilder(
builder: (lbCtx, constraints) {
const reservedBelow = 78.0;
final spectrumH = (constraints.maxHeight - reservedBelow)
final spectrumH = (constraints.maxHeight -
layout.reservedBelowControls)
.clamp(40.0, double.infinity);
return Column(
@@ -262,9 +270,9 @@ class AccountColorPanel extends StatelessWidget {
),
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
SizedBox(
height: 36,
height: layout.hueSliderHeight,
child: ColorPickerSlider(
TrackType.hue,
currentHSV,
@@ -272,14 +280,14 @@ class AccountColorPanel extends StatelessWidget {
displayThumbColor: true,
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
IgnorePointer(
ignoring: isSolid,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isSolid ? 0.4 : 1.0,
child: SizedBox(
height: 26,
height: layout.hexRowHeight,
child: Row(
children: [
GestureDetector(
@@ -411,7 +419,7 @@ class AccountColorPanel extends StatelessWidget {
},
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
IgnorePointer(
ignoring: isSolid,
child: AnimatedOpacity(
@@ -463,8 +471,8 @@ class AccountColorPanel extends StatelessWidget {
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 150),
padding: const EdgeInsets.symmetric(
vertical: 5,
padding: EdgeInsets.symmetric(
vertical: layout.compact ? 3 : 5,
),
decoration: BoxDecoration(
color: isSelected
@@ -523,7 +531,7 @@ class AccountColorPanel extends StatelessWidget {
),
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
Row(
children: [
Expanded(
@@ -554,10 +562,13 @@ class AccountColorPanel extends StatelessWidget {
setPanelState(() {});
dashboardState.overlayEntry?.markNeedsBuild();
},
icon: const Icon(Icons.restart_alt_rounded, size: 15),
icon: Icon(
Icons.restart_alt_rounded,
size: layout.compact ? 14 : 15,
),
label: Text(
s.reset,
style: const TextStyle(fontSize: 13),
style: TextStyle(fontSize: layout.compact ? 12 : 13),
),
style: OutlinedButton.styleFrom(
foregroundColor: Theme.of(
@@ -568,7 +579,9 @@ class AccountColorPanel extends StatelessWidget {
dashboardContext,
).colorScheme.onSurface.withOpacity(0.2),
),
padding: const EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.symmetric(
vertical: layout.buttonVerticalPadding,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
@@ -613,7 +626,9 @@ class AccountColorPanel extends StatelessWidget {
disabledForegroundColor: Theme.of(
dashboardContext,
).colorScheme.onSurface.withOpacity(0.38),
padding: const EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.symmetric(
vertical: layout.buttonVerticalPadding,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
@@ -622,9 +637,9 @@ class AccountColorPanel extends StatelessWidget {
dashboardState.isAddingAccount
? s.addAccount
: s.apply,
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14,
fontSize: layout.compact ? 13 : 14,
),
),
);
@@ -5,6 +5,8 @@ import 'package:sensors_plus/sensors_plus.dart';
import '../../../core/constants.dart';
import '../../../core/l10n/locale_provider.dart';
import '../../../core/services/card_color_service.dart';
import '../../../core/utils/card_layout.dart';
import '../../../shared/utils/card_gradient.dart';
import '../../../core/services/haptic_service.dart';
import '../../../shared/providers/amount_format_provider.dart';
import '../../../shared/widgets/byn_sign.dart';
@@ -83,47 +85,6 @@ class BalanceCardState extends ConsumerState<BalanceCard>
super.dispose();
}
Gradient _buildGradient(Color primary, Color secondary, GradientType type) {
final colorDark = Color.lerp(secondary, Colors.black, 0.3)!;
switch (type) {
case GradientType.linear:
return LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [primary, secondary, colorDark],
stops: const [0.0, 0.6, 1.0],
);
case GradientType.linearReverse:
return LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [primary, secondary, colorDark],
stops: const [0.0, 0.6, 1.0],
);
case GradientType.radial:
return RadialGradient(
center: Alignment.center,
radius: 1.4,
colors: [primary, secondary, colorDark],
stops: const [0.0, 0.6, 1.0],
);
case GradientType.sweep:
return SweepGradient(
center: Alignment.center,
startAngle: 0.0,
endAngle: 3.14159 * 2,
colors: [primary, secondary, colorDark, secondary, primary],
stops: const [0.0, 0.25, 0.5, 0.75, 1.0],
);
case GradientType.solid:
return LinearGradient(
colors: [primary, primary, primary],
stops: const [0.0, 0.5, 1.0],
);
}
}
@override
Widget build(BuildContext context) {
final s = ref.watch(stringsProvider);
@@ -171,10 +132,10 @@ class BalanceCardState extends ConsumerState<BalanceCard>
..rotateY(_tiltY * 0.42),
child: Container(
width: double.infinity,
height: 180,
height: kBalanceCardHeight,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
gradient: _buildGradient(primary, secondary, gradientType),
gradient: buildCardGradient(primary, secondary, gradientType),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.4),
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/services/card_color_service.dart';
import '../../../core/utils/card_layout.dart';
import '../../../core/services/haptic_service.dart';
import '../../../shared/models/account.dart';
import '../../../shared/models/transaction.dart';
@@ -66,7 +67,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
return Column(
children: [
SizedBox(
height: 190,
height: kBalanceCardCarouselHeight,
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width,
child: PageView.builder(
@@ -154,14 +155,14 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
);
},
loading: () => const SizedBox(
height: 180,
height: kBalanceCardCarouselHeight,
child: Center(child: CircularProgressIndicator()),
),
error: (error, stack) {
return Column(
children: [
SizedBox(
height: 180,
height: kBalanceCardCarouselHeight,
child: BalanceCard(
balance: widget.balance,
currencyInfo: widget.currencyInfo,
@@ -192,13 +193,13 @@ class AddAccountCard extends StatelessWidget {
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
vertical: 5,
),
child: CustomPaint(
painter: _DashedBorderPainter(),
child: Container(
width: double.infinity,
height: 165,
height: kAddAccountCardHeight,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.4),
borderRadius: BorderRadius.circular(20),
@@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/l10n/app_strings.dart';
import '../../../core/l10n/locale_provider.dart';
import '../../../core/services/card_color_service.dart';
import '../../../core/utils/card_layout.dart';
import '../../settings/provider.dart';
import '../provider.dart';
import 'balance_card.dart';
@@ -34,10 +35,11 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
@override
Widget build(BuildContext context) {
final mq = MediaQuery.of(widget.context);
final cardTop = mq.padding.top + kToolbarHeight + 16;
const cardHeight = 230.0;
final panelTop = cardTop + cardHeight + 65;
const panelHeight = 410.0;
final layout = CardOverlayLayout.fromMediaQuery(mq);
final cardTop = layout.cardTop;
final cardHeight = layout.cardHeight;
final panelTop = cardTop + cardHeight + layout.cardPreviewGap;
final panelHeight = layout.colorPanelHeight(mq, panelTop);
return Material(
color: Colors.transparent,
@@ -91,7 +93,7 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
child: GestureDetector(
onTap: () {},
behavior: HitTestBehavior.opaque,
child: _buildPanel(panelHeight),
child: _buildPanel(panelHeight, layout),
),
),
Positioned(
@@ -132,7 +134,7 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
);
}
Widget _buildPanel(double panelHeight) {
Widget _buildPanel(double panelHeight, CardOverlayLayout layout) {
return Container(
height: panelHeight,
decoration: BoxDecoration(
@@ -182,7 +184,12 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
: dash.tempSecondaryHSV;
return Padding(
padding: const EdgeInsets.fromLTRB(16, 14, 16, 22),
padding: EdgeInsets.fromLTRB(
16,
layout.panelPaddingTop,
16,
layout.panelPaddingBottom,
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -341,12 +348,12 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
],
),
),
const SizedBox(height: 10),
SizedBox(height: layout.tabSpacing),
Expanded(
child: LayoutBuilder(
builder: (lbCtx, constraints) {
const reservedBelow = 78.0;
final spectrumH = (constraints.maxHeight - reservedBelow)
final spectrumH = (constraints.maxHeight -
layout.reservedBelowControls)
.clamp(40.0, double.infinity);
return Column(
@@ -364,9 +371,9 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
),
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
SizedBox(
height: 36,
height: layout.hueSliderHeight,
child: ColorPickerSlider(
TrackType.hue,
currentHSV,
@@ -374,14 +381,14 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
displayThumbColor: true,
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
IgnorePointer(
ignoring: isSolid,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isSolid ? 0.4 : 1.0,
child: SizedBox(
height: 26,
height: layout.hexRowHeight,
child: Row(
children: [
GestureDetector(
@@ -499,7 +506,7 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
},
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
IgnorePointer(
ignoring: isSolid,
child: AnimatedOpacity(
@@ -545,8 +552,8 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 150),
padding: const EdgeInsets.symmetric(
vertical: 5,
padding: EdgeInsets.symmetric(
vertical: layout.compact ? 3 : 5,
),
decoration: BoxDecoration(
color: isSelected
@@ -605,7 +612,7 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
),
),
),
const SizedBox(height: 8),
SizedBox(height: layout.controlSpacing),
Row(
children: [
Expanded(
@@ -633,10 +640,13 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
setPanelState(() {});
dash.overlayEntry?.markNeedsBuild();
},
icon: const Icon(Icons.restart_alt_rounded, size: 15),
icon: Icon(
Icons.restart_alt_rounded,
size: layout.compact ? 14 : 15,
),
label: Text(
s.reset,
style: const TextStyle(fontSize: 13),
style: TextStyle(fontSize: layout.compact ? 12 : 13),
),
style: OutlinedButton.styleFrom(
foregroundColor: Theme.of(
@@ -647,7 +657,9 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
widget.context,
).colorScheme.onSurface.withOpacity(0.2),
),
padding: const EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.symmetric(
vertical: layout.buttonVerticalPadding,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
@@ -662,16 +674,18 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF7C6DED),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.symmetric(
vertical: layout.buttonVerticalPadding,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Text(
s.apply,
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14,
fontSize: layout.compact ? 13 : 14,
),
),
),