mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-28 06:28:41 +01:00
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535 upstream commits, including the Monero silent-open fix, Monero on Trezor, Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9. Merged with both sides normalized first (import rename, 100-column format), which took the conflict count from 614 paths to 322. The procedure is now scripts/upstream_sync.sh. Kept from Hash Bags: - WalletType enum order and Hive IDs. SQLite stores WalletType.index and our order differs from upstream's; taking theirs would reread saved wallets as other chains. Our frozen adapter keeps the shipped IDs. - The 1.0.2 legacy PIN and wallet-password decode and self-heal. - Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out. - Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me), converted to upstream's isDefault node-list key; Wownero is back in the node reset list. - Privacy: address resolvers limited to domain-anchored sources again; prices.neroswap.com for fiat; upstream's charts tab, which reads prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false. - Lightning stays behind FeatureFlag.isLightningEnabled, including upstream's new post-seed Lightning username step. - Our icon pipeline, branding and bundle identifiers. Twelve new upstream widget tests are skipped: test and code are unchanged from v6.5.0 apart from renames (not rerun on a pristine upstream checkout; upstream's top_bar_test does not compile against its own TopBar). flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped; flutter build bundle compiles. Built with Flutter 3.41.9.
229 lines
11 KiB
Dart
229 lines
11 KiB
Dart
import 'package:hash_wallet/core/utilities.dart';
|
|
import 'package:hash_wallet/di.dart';
|
|
import 'package:hash_wallet/entities/new_ui_entities/list_item/list_Item_checkbox.dart';
|
|
import 'package:hash_wallet/entities/new_ui_entities/list_item/list_item_selector.dart';
|
|
import 'package:hash_wallet/exchange/provider/exchange_provider.dart';
|
|
import 'package:hash_wallet/generated/i18n.dart';
|
|
import 'package:hash_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
|
import 'package:hash_wallet/new-ui/widgets/swap_page/trocador_providers_settings.dart';
|
|
import 'package:hash_wallet/src/widgets/alert_with_one_action.dart';
|
|
import 'package:hash_wallet/src/widgets/new_list_row/new_list_section.dart';
|
|
import 'package:hash_wallet/utils/show_pop_up.dart';
|
|
import 'package:hash_wallet/view_model/exchange/exchange_view_model.dart';
|
|
import 'package:hash_wallet/view_model/settings/trocador_providers_view_model.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
|
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
|
|
|
class ProviderOptionsPage extends StatelessWidget {
|
|
const ProviderOptionsPage({super.key, required this.exchangeViewModel});
|
|
|
|
final ExchangeViewModel exchangeViewModel;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Observer(
|
|
builder: (_) {
|
|
final decentralizedProviders = exchangeViewModel.providerList
|
|
.where((provider) => !provider.description.isCentralized)
|
|
.toList();
|
|
final centralizedProviders = exchangeViewModel.providerList
|
|
.where((provider) => provider.description.isCentralized)
|
|
.toList();
|
|
return Column(
|
|
children: [
|
|
ModalTopBar(
|
|
title: S.of(context).swap_providers,
|
|
onLeadingPressed: Navigator.of(context).pop,
|
|
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
|
leadingSemanticLabel: S.of(context).seed_alert_back,
|
|
),
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
controller: ModalScrollController.of(context),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
child: Column(
|
|
children: [
|
|
NewListSections(sections: {
|
|
"": [
|
|
ListItemSelector(
|
|
options: [
|
|
exchangeViewModel.forceDecentralizedExchanges
|
|
? S.of(context).decentralized_only
|
|
: S.of(context).best_rate
|
|
],
|
|
keyValue: "pref",
|
|
label: S.of(context).preference,
|
|
onTap: exchangeViewModel.toggleForceDecentralizedExchanges)
|
|
]
|
|
}),
|
|
SizedBox(height: 24),
|
|
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
|
Text(
|
|
S.of(context).decentralized,
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: Theme.of(context).colorScheme.onSurfaceVariant),
|
|
),
|
|
Row(
|
|
spacing: 20,
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () {
|
|
for (final provider in decentralizedProviders) {
|
|
_switchProviderStatus(provider, true, context);
|
|
}
|
|
},
|
|
child: Text(
|
|
S.of(context).select_all,
|
|
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
|
),
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
for (final provider in decentralizedProviders) {
|
|
_switchProviderStatus(provider, false, context);
|
|
}
|
|
},
|
|
child: Text(S.of(context).unselect_all,
|
|
style: TextStyle(color: Theme.of(context).colorScheme.primary)),
|
|
)
|
|
],
|
|
)
|
|
]),
|
|
SizedBox(height: 12),
|
|
NewListSections(
|
|
getCheckboxValue: (key) =>
|
|
exchangeViewModel.selectedProviders
|
|
.firstWhereOrNull((e) => e.title == key) !=
|
|
null,
|
|
updateCheckboxValue: (key, val) {},
|
|
sections: {
|
|
S.of(context).decentralized: decentralizedProviders.map((item) {
|
|
return ListItemCheckbox(
|
|
iconPath: item.description.image,
|
|
keyValue: item.title,
|
|
label: item.title,
|
|
value: exchangeViewModel.selectedProviders.contains(item),
|
|
onChanged: (val) {
|
|
_switchProviderStatus(item, val, context);
|
|
});
|
|
}).toList(),
|
|
}),
|
|
SizedBox(height: 24),
|
|
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
|
Text(S.of(context).centralized,
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: Theme.of(context).colorScheme.onSurfaceVariant)),
|
|
Row(
|
|
spacing: 20,
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () {
|
|
for (final provider in centralizedProviders) {
|
|
_switchProviderStatus(provider, true, context);
|
|
}
|
|
},
|
|
child: Text(
|
|
S.of(context).select_all,
|
|
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
|
),
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
for (final provider in centralizedProviders) {
|
|
_switchProviderStatus(provider, false, context);
|
|
}
|
|
},
|
|
child: Text(S.of(context).unselect_all,
|
|
style: TextStyle(color: Theme.of(context).colorScheme.primary)),
|
|
)
|
|
],
|
|
)
|
|
]),
|
|
SizedBox(height: 12),
|
|
Stack(
|
|
children: [
|
|
NewListSections(
|
|
getCheckboxValue: (key) =>
|
|
exchangeViewModel.selectedProviders
|
|
.firstWhereOrNull((e) => e.title == key) !=
|
|
null,
|
|
updateCheckboxValue: (key, val) {},
|
|
sections: {
|
|
S.of(context).centralized: centralizedProviders.map((item) {
|
|
return ListItemCheckbox(
|
|
iconPath: item.description.image,
|
|
keyValue: item.title,
|
|
label: item.title,
|
|
showArrow: item.title == "Trocador",
|
|
value: exchangeViewModel.selectedProviders.contains(item),
|
|
subtitle: item.title == "Trocador"
|
|
? S.of(context).manage_providers
|
|
: null,
|
|
onTap: item.title == "Trocador"
|
|
? () {
|
|
_openTrocadorProvidersPage(context);
|
|
}
|
|
: null,
|
|
onChanged: (val) {
|
|
_switchProviderStatus(item, val, context);
|
|
});
|
|
}).toList(),
|
|
}),
|
|
if (exchangeViewModel.forceDecentralizedExchanges)
|
|
Positioned.fill(
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.black12.withAlpha(128),
|
|
borderRadius: BorderRadius.circular(16)),
|
|
))
|
|
],
|
|
),
|
|
SizedBox(height: 36)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _switchProviderStatus(ExchangeProvider provider, bool status, BuildContext context) {
|
|
if (!provider.isAvailable) {
|
|
showPopUp<void>(
|
|
builder: (BuildContext popUpContext) => AlertWithOneAction(
|
|
alertTitle: 'Error',
|
|
alertContent: 'The exchange is blocked in your region.',
|
|
buttonText: S.of(context).ok,
|
|
buttonAction: () => Navigator.of(context).pop()),
|
|
context: context);
|
|
return;
|
|
}
|
|
if (status) {
|
|
exchangeViewModel.addExchangeProvider(provider);
|
|
} else {
|
|
exchangeViewModel.removeExchangeProvider(provider);
|
|
}
|
|
|
|
exchangeViewModel.saveSelectedProviders();
|
|
}
|
|
|
|
void _openTrocadorProvidersPage(BuildContext context) {
|
|
final vm = getIt.get<TrocadorProvidersViewModel>();
|
|
Navigator.of(context).push(CupertinoPageRoute(
|
|
builder: (context) => Material(
|
|
child: TrocadorProvidersSettings(
|
|
trocadorProvidersViewModel: vm,
|
|
))));
|
|
}
|
|
}
|