This commit is contained in:
2026-06-28 15:10:17 +03:00
parent 2b89545248
commit f2d444cb16
5 changed files with 114 additions and 15 deletions
@@ -87,15 +87,15 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
final mq = MediaQuery.of(widget.context); final mq = MediaQuery.of(widget.context);
final layout = CardOverlayLayout.fromMediaQuery(mq); final layout = CardOverlayLayout.fromMediaQuery(mq);
final cardTop = layout.cardTop; final cardTop = layout.cardTop;
final cardHeight = layout.cardHeight;
final editorPanelHeight = layout.editorPanelHeight; final editorPanelHeight = layout.editorPanelHeight;
final editorPanelTop = cardTop + cardHeight + layout.sectionGap;
final colorPanelTop = editorPanelTop + editorPanelHeight + layout.sectionGap;
final colorPanelHeight = layout.colorPanelHeight(mq, colorPanelTop);
return Consumer( return Consumer(
builder: (context, ref, _) { builder: (context, ref, _) {
final exchangeService = ref.watch(exchangeRateServiceProvider); final exchangeService = ref.watch(exchangeRateServiceProvider);
final cardHeight = ref.watch(cardHeightProvider);
final editorPanelTop = cardTop + cardHeight + layout.sectionGap;
final colorPanelTop = editorPanelTop + editorPanelHeight + layout.sectionGap;
final colorPanelHeight = layout.colorPanelHeight(mq, colorPanelTop);
double previewBalance = 0.0; double previewBalance = 0.0;
if (!dash.isAddingAccount) { if (!dash.isAddingAccount) {
@@ -220,11 +220,38 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
Brightness.dark Brightness.dark
? dash.tempDarkGradientType ? dash.tempDarkGradientType
: dash.tempLightGradientType, : dash.tempLightGradientType,
cardHeight: cardHeight,
), ),
), ),
), ),
), ),
), ),
Positioned(
top: cardTop - 28,
left: 0,
right: 0,
child: Center(
child: _HeightHandle(
onDrag: (delta) {
final newHeight = cardHeight - delta * 2;
ref.read(cardHeightProvider.notifier).set(newHeight);
},
),
),
),
Positioned(
top: cardTop + cardHeight + 6,
left: 0,
right: 0,
child: Center(
child: _HeightHandle(
onDrag: (delta) {
final newHeight = cardHeight + delta * 2;
ref.read(cardHeightProvider.notifier).set(newHeight);
},
),
),
),
Positioned( Positioned(
top: editorPanelTop, top: editorPanelTop,
left: 20, left: 20,
@@ -468,3 +495,36 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
); );
} }
} }
class _HeightHandle extends StatefulWidget {
final ValueChanged<double> onDrag;
const _HeightHandle({required this.onDrag});
@override
State<_HeightHandle> createState() => _HeightHandleState();
}
class _HeightHandleState extends State<_HeightHandle> {
bool _active = false;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return GestureDetector(
onVerticalDragStart: (_) => setState(() => _active = true),
onVerticalDragUpdate: (details) => widget.onDrag(details.delta.dy),
onVerticalDragEnd: (_) => setState(() => _active = false),
behavior: HitTestBehavior.opaque,
child: AnimatedContainer(
duration: const Duration(milliseconds: 150),
width: _active ? 56 : 44,
height: _active ? 6 : 4,
decoration: BoxDecoration(
color: theme.colorScheme.onSurface.withOpacity(_active ? 0.5 : 0.25),
borderRadius: BorderRadius.circular(3),
),
),
);
}
}
@@ -37,6 +37,7 @@ class BalanceCard extends ConsumerStatefulWidget {
final GradientType? previewGradientType; final GradientType? previewGradientType;
final String? accountName; final String? accountName;
final CardColors? accountColors; final CardColors? accountColors;
final double? cardHeight;
const BalanceCard({ const BalanceCard({
super.key, super.key,
@@ -48,6 +49,7 @@ class BalanceCard extends ConsumerStatefulWidget {
this.previewGradientType, this.previewGradientType,
this.accountName, this.accountName,
this.accountColors, this.accountColors,
this.cardHeight,
}); });
@override @override
@@ -132,7 +134,7 @@ class BalanceCardState extends ConsumerState<BalanceCard>
..rotateY(_tiltY * 0.42), ..rotateY(_tiltY * 0.42),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
height: kBalanceCardHeight, height: widget.cardHeight ?? kBalanceCardHeight,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
gradient: buildCardGradient(primary, secondary, gradientType), gradient: buildCardGradient(primary, secondary, gradientType),
@@ -59,6 +59,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final accountsAsync = ref.watch(accountsProvider); final accountsAsync = ref.watch(accountsProvider);
final activeIndex = ref.watch(activeAccountIndexProvider); final activeIndex = ref.watch(activeAccountIndexProvider);
final cardHeight = ref.watch(cardHeightProvider);
return accountsAsync.when( return accountsAsync.when(
data: (accounts) { data: (accounts) {
@@ -67,7 +68,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
return Column( return Column(
children: [ children: [
SizedBox( SizedBox(
height: kBalanceCardCarouselHeight, height: cardHeight + 10,
child: OverflowBox( child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width, maxWidth: MediaQuery.of(context).size.width,
child: PageView.builder( child: PageView.builder(
@@ -96,6 +97,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
previewPrimary: widget.previewPrimary, previewPrimary: widget.previewPrimary,
previewSecondary: widget.previewSecondary, previewSecondary: widget.previewSecondary,
previewGradientType: widget.previewGradientType, previewGradientType: widget.previewGradientType,
cardHeight: cardHeight,
); );
} else if (index <= accounts.length) { } else if (index <= accounts.length) {
final account = accounts[index - 1]; final account = accounts[index - 1];
@@ -134,10 +136,12 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
widget.onAccountLongPress?.call(account), widget.onAccountLongPress?.call(account),
accountName: account.name, accountName: account.name,
accountColors: accountColors, accountColors: accountColors,
cardHeight: cardHeight,
); );
} else { } else {
cardWidget = AddAccountCard( cardWidget = AddAccountCard(
onTap: widget.onAddAccountTap, onTap: widget.onAddAccountTap,
cardHeight: cardHeight,
); );
} }
@@ -154,15 +158,15 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
], ],
); );
}, },
loading: () => const SizedBox( loading: () => SizedBox(
height: kBalanceCardCarouselHeight, height: cardHeight + 10,
child: Center(child: CircularProgressIndicator()), child: const Center(child: CircularProgressIndicator()),
), ),
error: (error, stack) { error: (error, stack) {
return Column( return Column(
children: [ children: [
SizedBox( SizedBox(
height: kBalanceCardCarouselHeight, height: cardHeight + 10,
child: BalanceCard( child: BalanceCard(
balance: widget.balance, balance: widget.balance,
currencyInfo: widget.currencyInfo, currencyInfo: widget.currencyInfo,
@@ -170,6 +174,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
previewPrimary: widget.previewPrimary, previewPrimary: widget.previewPrimary,
previewSecondary: widget.previewSecondary, previewSecondary: widget.previewSecondary,
previewGradientType: widget.previewGradientType, previewGradientType: widget.previewGradientType,
cardHeight: cardHeight,
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@@ -183,8 +188,9 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
class AddAccountCard extends StatelessWidget { class AddAccountCard extends StatelessWidget {
final VoidCallback? onTap; final VoidCallback? onTap;
final double? cardHeight;
const AddAccountCard({super.key, this.onTap}); const AddAccountCard({super.key, this.onTap, this.cardHeight});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -199,7 +205,7 @@ class AddAccountCard extends StatelessWidget {
painter: _DashedBorderPainter(), painter: _DashedBorderPainter(),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
height: kAddAccountCardHeight, height: cardHeight ?? kAddAccountCardHeight,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.4), color: Theme.of(context).colorScheme.surface.withOpacity(0.4),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
@@ -37,9 +37,12 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
final mq = MediaQuery.of(widget.context); final mq = MediaQuery.of(widget.context);
final layout = CardOverlayLayout.fromMediaQuery(mq); final layout = CardOverlayLayout.fromMediaQuery(mq);
final cardTop = layout.cardTop; final cardTop = layout.cardTop;
final cardHeight = layout.cardHeight;
final panelTop = cardTop + cardHeight + layout.cardPreviewGap; return Consumer(
final panelHeight = layout.colorPanelHeight(mq, panelTop); builder: (context, ref, _) {
final cardHeight = ref.watch(cardHeightProvider);
final panelTop = cardTop + cardHeight + layout.cardPreviewGap;
final panelHeight = layout.colorPanelHeight(mq, panelTop);
return Material( return Material(
color: Colors.transparent, color: Colors.transparent,
@@ -80,6 +83,7 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
Theme.of(widget.context).brightness == Brightness.dark Theme.of(widget.context).brightness == Brightness.dark
? dash.tempDarkGradientType ? dash.tempDarkGradientType
: dash.tempLightGradientType, : dash.tempLightGradientType,
cardHeight: cardHeight,
), ),
), ),
), ),
@@ -132,6 +136,8 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
], ],
), ),
); );
},
);
} }
Widget _buildPanel(double panelHeight, CardOverlayLayout layout) { Widget _buildPanel(double panelHeight, CardOverlayLayout layout) {
+25
View File
@@ -103,6 +103,31 @@ final exchangeRateServiceProvider = Provider<ExchangeRateService>((ref) {
return ExchangeRateService(prefs); return ExchangeRateService(prefs);
}); });
final cardHeightProvider = NotifierProvider<CardHeightNotifier, double>(
CardHeightNotifier.new,
);
class CardHeightNotifier extends Notifier<double> {
static const _key = 'card_height';
static const _minHeight = 160.0;
static const _maxHeight = 280.0;
static const _defaultHeight = 200.0;
@override
double build() {
final prefs = ref.watch(sharedPreferencesProvider);
final saved = prefs.getDouble(_key);
if (saved == null) return _defaultHeight;
return saved.clamp(_minHeight, _maxHeight);
}
void set(double height) {
final clamped = height.clamp(_minHeight, _maxHeight);
state = clamped;
ref.read(sharedPreferencesProvider).setDouble(_key, clamped);
}
}
final ratesInitProvider = FutureProvider<void>((ref) async { final ratesInitProvider = FutureProvider<void>((ref) async {
await ref.read(exchangeRateServiceProvider).fetchRates(); await ref.read(exchangeRateServiceProvider).fetchRates();
}); });