Skip to content

Commit d3acdcf

Browse files
feat: search functionality in settings
1 parent a8d0725 commit d3acdcf

41 files changed

Lines changed: 2440 additions & 410 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

lib/core/widgets/settings_entry_item.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
44
class SettingsEntryItem extends StatelessWidget {
55
final IconData icon;
66
final String title;
7+
final String? subtitle;
78
final VoidCallback? onTap;
89
final Color? iconColor;
910
final Color? textColor;
@@ -15,6 +16,7 @@ class SettingsEntryItem extends StatelessWidget {
1516
super.key,
1617
required this.icon,
1718
required this.title,
19+
this.subtitle,
1820
this.onTap,
1921
this.iconColor,
2022
this.textColor,
@@ -44,6 +46,16 @@ class SettingsEntryItem extends StatelessWidget {
4446
color: textColor ?? context.appColors.onSurface,
4547
),
4648
),
49+
subtitle: subtitle == null
50+
? null
51+
: Text(
52+
subtitle!,
53+
maxLines: 2,
54+
overflow: TextOverflow.ellipsis,
55+
style: theme.textTheme.bodySmall?.copyWith(
56+
color: context.appColors.textMuted,
57+
),
58+
),
4759
trailing: trailing ?? const Icon(Icons.chevron_right),
4860
onTap: onTap,
4961
);

lib/features/backup_settings/ui/screens/backup_settings_screen.dart

Lines changed: 22 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ import 'package:bb_mobile/features/backup_settings/presentation/backup_settings_
66
import 'package:bb_mobile/features/backup_settings/presentation/cubit/backup_settings_cubit.dart';
77
import 'package:bb_mobile/features/backup_settings/ui/backup_settings_router.dart';
88
import 'package:bb_mobile/features/backup_settings/ui/widgets/view_vault_key_warning_bottom_sheet.dart';
9-
import 'package:bb_mobile/features/labels/labels_facade.dart';
10-
import 'package:bb_mobile/features/transactions/ui/transactions_router.dart';
119
import 'package:bb_mobile/features/recoverbull/presentation/bloc.dart';
1210
import 'package:bb_mobile/features/recoverbull/router.dart';
11+
import 'package:bb_mobile/features/settings/ui/settings_item.dart';
1312
import 'package:bb_mobile/locator.dart';
1413
import 'package:bb_mobile/core/widgets/snackbar_utils.dart';
1514
import 'package:flutter/material.dart';
@@ -49,6 +48,10 @@ class _Screen extends StatelessWidget {
4948
},
5049
child: BlocBuilder<BackupSettingsCubit, BackupSettingsState>(
5150
builder: (context, state) {
51+
final items = buildSettingsItems(
52+
localization: context.loc,
53+
exchangeTitle: context.loc.settingsExchangeSettingsTitle,
54+
);
5255
return Scaffold(
5356
appBar: AppBar(
5457
forceMaterialTransparency: true,
@@ -70,15 +73,28 @@ class _Screen extends StatelessWidget {
7073
child: _BackupTestStatusWidget(),
7174
),
7275
const Gap(40),
73-
const _StartBackupButton(),
76+
items
77+
.byId(SettingsItemId.startBackup)
78+
.buildTile(
79+
context,
80+
iconColor: context.appColors.primary,
81+
),
7482
if (state.lastEncryptedBackup != null)
7583
const _ViewVaultKeyButton(),
7684
if (state.lastEncryptedBackup != null ||
7785
state.lastPhysicalBackup != null)
7886
const _TestBackupButton(),
79-
const _RecoverBullSettingsButton(),
80-
const _Bip329LabelsButton(),
81-
const _TransactionHistoryButton(),
87+
items
88+
.byId(SettingsItemId.recoverbull)
89+
.buildTile(
90+
context,
91+
iconColor: context.appColors.secondary,
92+
textColor: context.appColors.secondary,
93+
),
94+
items.byId(SettingsItemId.labels).buildTile(context),
95+
items
96+
.byId(SettingsItemId.transactionHistory)
97+
.buildTile(context),
8298
],
8399
),
84100
),
@@ -160,23 +176,6 @@ class _TestBackupButton extends StatelessWidget {
160176
}
161177
}
162178

163-
class _StartBackupButton extends StatelessWidget {
164-
const _StartBackupButton();
165-
166-
@override
167-
Widget build(BuildContext context) {
168-
return SettingsEntryItem(
169-
icon: Icons.save_as,
170-
iconColor: context.appColors.primary,
171-
title: context.loc.backupSettingsStartBackup,
172-
onTap: () => context.pushNamed(
173-
BackupSettingsSubroute.backupOptions.name,
174-
extra: BackupSettingsFlow.backup,
175-
),
176-
);
177-
}
178-
}
179-
180179
class _ViewVaultKeyButton extends StatelessWidget {
181180
const _ViewVaultKeyButton();
182181

@@ -201,52 +200,3 @@ class _ViewVaultKeyButton extends StatelessWidget {
201200
);
202201
}
203202
}
204-
205-
class _TransactionHistoryButton extends StatelessWidget {
206-
const _TransactionHistoryButton();
207-
208-
@override
209-
Widget build(BuildContext context) {
210-
return SettingsEntryItem(
211-
icon: Icons.file_download,
212-
title: context.loc.transactionHistoryTitle,
213-
onTap: () => context.pushNamed(TransactionsRoute.exportTransactions.name),
214-
);
215-
}
216-
}
217-
218-
class _Bip329LabelsButton extends StatelessWidget {
219-
const _Bip329LabelsButton();
220-
221-
@override
222-
Widget build(BuildContext context) {
223-
return SettingsEntryItem(
224-
icon: Icons.sell,
225-
title: context.loc.backupSettingsLabelsButton,
226-
onTap: () => context.push(LabelsRouter.route.path),
227-
);
228-
}
229-
}
230-
231-
class _RecoverBullSettingsButton extends StatelessWidget {
232-
const _RecoverBullSettingsButton();
233-
234-
@override
235-
Widget build(BuildContext context) {
236-
return SettingsEntryItem(
237-
icon: Icons.cloud_circle,
238-
iconColor: context.appColors.secondary,
239-
textColor: context.appColors.secondary,
240-
title: context.loc.backupSettingsRecoverBullSettings,
241-
onTap: () {
242-
context.pushNamed(
243-
RecoverBullRoute.recoverbullFlows.name,
244-
extra: RecoverBullFlowsExtra(
245-
flow: RecoverBullFlow.settings,
246-
vault: null,
247-
),
248-
);
249-
},
250-
);
251-
}
252-
}

lib/features/settings/ui/screens/all_settings_screen.dart

Lines changed: 47 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import 'dart:io';
33
import 'package:bb_mobile/core/themes/app_theme.dart';
44
import 'package:bb_mobile/core/utils/build_context_x.dart';
55
import 'package:bb_mobile/core/utils/constants.dart';
6-
import 'package:bb_mobile/core/widgets/settings_entry_item.dart';
76
import 'package:bb_mobile/features/exchange/presentation/exchange_cubit.dart';
87
import 'package:bb_mobile/features/exchange/ui/exchange_router.dart';
98
import 'package:bb_mobile/features/exchange_support_chat/public/exchange_support_chat_facade.dart';
109
import 'package:bb_mobile/features/settings/presentation/bloc/settings_cubit.dart';
11-
import 'package:bb_mobile/features/settings/ui/settings_router.dart';
10+
import 'package:bb_mobile/features/settings/ui/settings_item.dart';
11+
import 'package:bb_mobile/features/settings/ui/widgets/settings_search_sheet.dart';
1212
import 'package:bb_mobile/features/status_check/presentation/cubit.dart';
13-
import 'package:bb_mobile/features/status_check/router.dart';
1413
import 'package:bull_ui/bull_ui.dart' show Gap;
1514
import 'package:flutter/material.dart';
1615
import 'package:flutter/services.dart';
@@ -33,6 +32,12 @@ class _AllSettingsScreenState extends State<AllSettingsScreen> {
3332
context.read<ServiceStatusCubit>().checkStatus();
3433
}
3534

35+
Future<void> _openSettingsSearch(List<SettingsItem> items) async {
36+
final item = await SettingsSearchSheet.show(context: context, items: items);
37+
if (item == null || !mounted) return;
38+
item.open(context);
39+
}
40+
3641
@override
3742
Widget build(BuildContext context) {
3843
final theme = Theme.of(context);
@@ -44,6 +49,9 @@ class _AllSettingsScreenState extends State<AllSettingsScreen> {
4449
final isSuperuser =
4550
context.select((SettingsCubit cubit) => cubit.state.isSuperuser) ??
4651
false;
52+
final isDevModeEnabled =
53+
context.select((SettingsCubit cubit) => cubit.state.isDevModeEnabled) ??
54+
false;
4755

4856
final serviceStatusLoading = context.select(
4957
(ServiceStatusCubit cubit) => cubit.state.isLoading,
@@ -53,110 +61,49 @@ class _AllSettingsScreenState extends State<AllSettingsScreen> {
5361
(ServiceStatusCubit cubit) => cubit.state.serviceStatus,
5462
);
5563

64+
final exchangeTitle = Platform.isIOS && !isSuperuser
65+
? context.loc.settingsAccountSettingsTitle
66+
: context.loc.settingsExchangeSettingsTitle;
67+
final items = buildSettingsItems(
68+
localization: context.loc,
69+
exchangeTitle: exchangeTitle,
70+
isSuperuser: isSuperuser,
71+
isDevModeEnabled: isDevModeEnabled,
72+
);
73+
5674
return Scaffold(
57-
appBar: AppBar(title: Text(context.loc.settingsScreenTitle)),
75+
appBar: AppBar(
76+
title: Text(context.loc.settingsScreenTitle),
77+
actionsPadding: const EdgeInsets.only(right: 8),
78+
actions: [
79+
IconButton(
80+
key: const Key('settings-search-button'),
81+
tooltip: context.loc.settingsSearchHint,
82+
color: context.appColors.secondary,
83+
iconSize: 32,
84+
icon: const Icon(Icons.search),
85+
onPressed: () => _openSettingsSearch(items),
86+
),
87+
],
88+
),
5889
body: SafeArea(
5990
child: SingleChildScrollView(
6091
child: Padding(
6192
padding: const EdgeInsets.symmetric(horizontal: 16),
6293
child: Column(
6394
children: [
64-
SettingsEntryItem(
65-
icon: Icons.currency_exchange,
66-
title: Platform.isIOS && !isSuperuser
67-
? context.loc.settingsAccountSettingsTitle
68-
: context.loc.settingsExchangeSettingsTitle,
69-
onTap: () {
70-
if (Platform.isIOS) {
71-
if (isSuperuser) {
72-
final notLoggedIn = context
73-
.read<ExchangeCubit>()
74-
.state
75-
.notLoggedIn;
76-
if (notLoggedIn) {
77-
context.goNamed(ExchangeRoute.exchangeLanding.name);
78-
} else {
79-
context.pushNamed(
80-
SettingsRoute.exchangeSettings.name,
81-
);
82-
}
83-
} else {
84-
final notLoggedIn = context
85-
.read<ExchangeCubit>()
86-
.state
87-
.notLoggedIn;
88-
if (notLoggedIn) {
89-
context.goNamed(ExchangeRoute.exchangeLanding.name);
90-
} else {
91-
context.pushNamed(
92-
SettingsRoute.exchangeSettings.name,
93-
);
94-
}
95-
}
96-
} else {
97-
final notLoggedIn = context
98-
.read<ExchangeCubit>()
99-
.state
100-
.notLoggedIn;
101-
if (notLoggedIn) {
102-
context.goNamed(ExchangeRoute.exchangeLanding.name);
103-
} else {
104-
context.pushNamed(SettingsRoute.exchangeSettings.name);
105-
}
106-
}
107-
},
108-
),
109-
SettingsEntryItem(
110-
icon: Icons.save,
111-
title: context.loc.settingsWalletBackupTitle,
112-
onTap: () {
113-
context.pushNamed(SettingsRoute.backupSettings.name);
114-
},
115-
),
116-
SettingsEntryItem(
117-
icon: Icons.currency_bitcoin,
118-
title: context.loc.settingsBitcoinSettingsTitle,
119-
onTap: () {
120-
context.pushNamed(SettingsRoute.bitcoinSettings.name);
121-
},
122-
),
123-
SettingsEntryItem(
124-
icon: Icons.app_settings_alt,
125-
title: context.loc.settingsAppSettingsTitle,
126-
onTap: () {
127-
context.pushNamed(SettingsRoute.appSettings.name);
128-
},
129-
),
130-
131-
SettingsEntryItem(
132-
icon: Icons.map,
133-
title: context.loc.settingsBtcMapTitle,
134-
onTap: () {
135-
context.pushNamed(SettingsRoute.btcMap.name);
136-
},
137-
),
138-
SettingsEntryItem(
139-
icon: Icons.description,
140-
title: context.loc.settingsTermsOfServiceTitle,
141-
onTap: () {
142-
final url = Uri.parse(
143-
SettingsConstants.termsAndConditionsLink,
144-
);
145-
launchUrl(url, mode: LaunchMode.inAppBrowserView);
146-
},
147-
),
148-
SettingsEntryItem(
149-
icon: Icons.monitor_heart,
150-
iconColor: serviceStatusLoading
151-
? context.appColors.textMuted
152-
: serviceStatus.allServicesOnline
153-
? context.appColors.success
154-
: context.appColors.error,
155-
title: context.loc.settingsServicesStatusTitle,
156-
onTap: () {
157-
context.pushNamed(StatusCheckRoute.serviceStatus.name);
158-
},
159-
),
95+
const Gap(16),
96+
for (final item in items.inSection(SettingsItemSection.root))
97+
item.buildTile(
98+
context,
99+
iconColor: item.id == SettingsItemId.servicesStatus
100+
? serviceStatusLoading
101+
? context.appColors.textMuted
102+
: serviceStatus.allServicesOnline
103+
? context.appColors.success
104+
: context.appColors.error
105+
: null,
106+
),
160107
],
161108
),
162109
),

0 commit comments

Comments
 (0)