mirror of
https://github.com/koloideal/Casha.git
synced 2026-08-08 17:51:14 +03:00
step
This commit is contained in:
@@ -362,12 +362,9 @@ final recentTransactionsProvider = Provider<List<Transaction>>((ref) {
|
||||
return ref.watch(filteredTransactionsProvider).take(20).toList();
|
||||
});
|
||||
|
||||
final accountsProvider = StreamProvider<List<Account>>((ref) async* {
|
||||
final accountsProvider = StreamProvider<List<Account>>((ref) {
|
||||
final repository = ref.watch(accountRepositoryProvider);
|
||||
while (true) {
|
||||
yield await repository.getAll();
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
return repository.watchAll();
|
||||
});
|
||||
|
||||
final activeAccountIndexProvider = NotifierProvider<_ActiveAccountIndexNotifier, int>(
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user