Skip to content

Commit f0ad4a2

Browse files
authored
Merge branch 'develop' into exchange-announcements
2 parents fd4373e + 5818eab commit f0ad4a2

50 files changed

Lines changed: 25876 additions & 121496 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import 'dart:convert';
2+
import 'dart:math';
3+
import 'dart:typed_data';
4+
5+
import 'package:bb_mobile/core/errors/bull_exception.dart';
6+
import 'package:bb_mobile/core/exchange/domain/entity/support_chat_message_attachment.dart';
7+
import 'package:bb_mobile/core/utils/logger.dart';
8+
import 'package:intl/intl.dart';
9+
10+
class CreateLogAttachmentUsecase {
11+
Future<SupportChatMessageAttachment> execute() async {
12+
try {
13+
List<String> logs;
14+
try {
15+
logs = await log.readLogs();
16+
} catch (e) {
17+
logs = [
18+
'timestamp\tlevel\tmessage\terror\ttrace',
19+
'${DateTime.now().toIso8601String()}\tINFO\tNo logs file found or logs could not be read: $e\t\t',
20+
];
21+
}
22+
23+
if (logs.isEmpty) {
24+
logs = [
25+
'timestamp\tlevel\tmessage\terror\ttrace',
26+
'${DateTime.now().toIso8601String()}\tINFO\tNo logs have been recorded yet\t\t',
27+
];
28+
}
29+
30+
final logContent = logs.join('\n');
31+
final bytes = Uint8List.fromList(utf8.encode(logContent));
32+
33+
final random = Random();
34+
final timestamp = DateFormat('yyyyMMdd_HHmmss').format(DateTime.now());
35+
36+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
37+
final randomAlphanumeric = String.fromCharCodes(
38+
Iterable.generate(
39+
8,
40+
(_) => chars.codeUnitAt(random.nextInt(chars.length)),
41+
),
42+
);
43+
44+
final fileName = '$timestamp.BullLog.$randomAlphanumeric.txt';
45+
46+
return SupportChatMessageAttachment(
47+
attachmentId: 'temp_logs_${DateTime.now().millisecondsSinceEpoch}',
48+
fileName: fileName,
49+
fileType: 'text/plain',
50+
fileSize: bytes.length,
51+
fileData: bytes,
52+
createdAt: DateTime.now(),
53+
);
54+
} catch (e) {
55+
throw CreateLogAttachmentException('$e');
56+
}
57+
}
58+
}
59+
60+
class CreateLogAttachmentException extends BullException {
61+
CreateLogAttachmentException(super.message);
62+
}

lib/core/exchange/exchange_locator.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import 'package:bb_mobile/core/exchange/domain/repositories/exchange_user_reposi
1919
import 'package:bb_mobile/core/exchange/domain/repositories/price_repository.dart';
2020
import 'package:bb_mobile/core/exchange/domain/usecases/convert_currency_to_sats_amount_usecase.dart';
2121
import 'package:bb_mobile/core/exchange/domain/usecases/convert_sats_to_currency_amount_usecase.dart';
22+
import 'package:bb_mobile/core/exchange/domain/usecases/create_log_attachment_usecase.dart';
2223
import 'package:bb_mobile/core/exchange/domain/usecases/delete_exchange_api_key_usecase.dart';
2324
import 'package:bb_mobile/core/exchange/domain/usecases/get_available_currencies_usecase.dart';
2425
import 'package:bb_mobile/core/exchange/domain/usecases/get_exchange_funding_details_usecase.dart';
@@ -475,6 +476,10 @@ class ExchangeLocator {
475476
),
476477
);
477478

479+
locator.registerFactory<CreateLogAttachmentUsecase>(
480+
() => CreateLogAttachmentUsecase(),
481+
);
482+
478483
locator.registerFactory<LabelExchangeOrdersUsecase>(
479484
() => LabelExchangeOrdersUsecase(
480485
labelDatasource: locator<LabelDatasource>(),

lib/core/settings/domain/settings_entity.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ enum Language {
4848
russian('ru', 'RU', 'Русский'),
4949
german('de', 'DE', 'Deutsch'),
5050
italian('it', 'IT', 'Italiano'),
51-
portuguese('pt', 'PT', 'Português');
51+
portuguese('pt', 'PT', 'Português'),
52+
simplifiedChinese('zh', 'CN', '简体中文');
5253

5354
final String languageCode;
5455
final String? countryCode;

lib/core/storage/migrations/schema_10_to_11.dart

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,39 +47,40 @@ class Schema10To11 {
4747

4848
// Delete any existing custom entries for the fulcrum server
4949
await (m.database.delete(electrumServers)..where(
50-
(e) =>
50+
(t) =>
5151
electrumServers.url.equals(fulcrumUrl) |
5252
electrumServers.url.equals(fulcrumUrlWithoutProtocol),
5353
))
5454
.go();
5555

56-
// Get all Bitcoin mainnet servers and update their priority
57-
final serversToUpdate =
56+
// Get all Bitcoin mainnet servers to update their priority
57+
final btcMainnetServers =
5858
await (m.database.select(electrumServers)..where(
59-
(e) =>
59+
(t) =>
6060
electrumServers.isTestnet.equals(0) &
6161
electrumServers.isLiquid.equals(0),
6262
))
6363
.get();
6464

65-
for (final server in serversToUpdate) {
66-
final url = server.read('url') as String;
67-
final isTestnet = server.read('is_testnet') as bool;
68-
final isLiquid = server.read('is_liquid') as bool;
69-
final priority = server.read('priority') as int;
70-
final isCustom = server.read('is_custom') as bool;
65+
// Update each server's priority by incrementing it
66+
for (final server in btcMainnetServers) {
67+
final serverUrl = server.data['url'] as String;
68+
final serverIsTestnet = server.data['is_testnet'] as int;
69+
final serverIsLiquid = server.data['is_liquid'] as int;
70+
final serverPriority = server.data['priority'] as int;
71+
final serverIsCustom = server.data['is_custom'] as int;
7172

72-
await m.database
73-
.into(electrumServers)
74-
.insertOnConflictUpdate(
75-
RawValuesInsertable({
76-
'url': Constant(url),
77-
'is_testnet': Constant(isTestnet),
78-
'is_liquid': Constant(isLiquid),
79-
'priority': Constant(priority + 1),
80-
'is_custom': Constant(isCustom),
81-
}),
82-
);
73+
await (m.database.update(
74+
electrumServers,
75+
)..where((t) => electrumServers.url.equals(serverUrl))).write(
76+
RawValuesInsertable({
77+
'url': Constant<String>(serverUrl),
78+
'is_testnet': Constant<int>(serverIsTestnet),
79+
'is_liquid': Constant<int>(serverIsLiquid),
80+
'priority': Constant<int>(serverPriority + 1),
81+
'is_custom': Constant<int>(serverIsCustom),
82+
}),
83+
);
8384
}
8485

8586
await m.database
@@ -131,10 +132,10 @@ class Schema10To11 {
131132
.into(mempoolServers)
132133
.insert(
133134
RawValuesInsertable({
134-
'url': Constant(server['url']),
135-
'is_testnet': Constant(server['isTestnet']),
136-
'is_liquid': Constant(server['isLiquid']),
137-
'is_custom': Constant(server['isCustom']),
135+
'url': Constant(server['url'] as String),
136+
'is_testnet': Constant(server['isTestnet'] as bool),
137+
'is_liquid': Constant(server['isLiquid'] as bool),
138+
'is_custom': Constant(server['isCustom'] as bool),
138139
}),
139140
mode: InsertMode.insertOrReplace,
140141
);

lib/core/widgets/inputs/paste_input.dart

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,22 @@ class PasteInput extends StatelessWidget {
2929
children: [
3030
const Gap(15),
3131
Expanded(
32-
child:
33-
text.isEmpty
34-
? BBText(
35-
hint,
36-
style: context.font.labelSmall,
37-
color: context.appColors.textMuted,
38-
)
39-
: BBText(
40-
text.trim(),
41-
style: context.font.bodyLarge,
42-
color: context.appColors.text,
43-
),
32+
child: text.isEmpty
33+
? BBText(
34+
hint,
35+
style: context.font.labelSmall,
36+
color: context.appColors.onSurface,
37+
)
38+
: BBText(
39+
text.trim(),
40+
style: context.font.bodyLarge,
41+
color: context.appColors.onSurface,
42+
),
4443
),
4544
IconButton(
4645
visualDensity: VisualDensity.compact,
4746
iconSize: 20,
48-
icon: Icon(Icons.paste_sharp, color: context.appColors.text),
47+
icon: Icon(Icons.paste_sharp, color: context.appColors.onSurface),
4948
onPressed: () {
5049
Clipboard.getData(Clipboard.kTextPlain).then((value) {
5150
if (value != null) {

lib/features/address_view/ui/screens/addresses_screen.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,7 @@ class _AddressesScreenState extends State<AddressesScreen> {
6464
@override
6565
Widget build(BuildContext context) {
6666
return Scaffold(
67-
appBar: AppBar(
68-
title: Text(context.loc.addressViewAddressesTitle),
69-
scrolledUnderElevation: 0,
70-
backgroundColor: context.appColors.transparent,
71-
elevation: 0,
72-
),
67+
appBar: AppBar(title: Text(context.loc.addressViewAddressesTitle)),
7368
body: SafeArea(
7469
child: Column(
7570
children: [

lib/features/ark/ui/receive_page.dart

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,9 @@ class _ReceivePageState extends State<ReceivePage> {
5656
),
5757
const Gap(16),
5858
ReceiveQR(
59-
qrData:
60-
_selectedOption! == context.loc.arkReceiveSegmentBoarding
61-
? btcAddress
62-
: arkAddress,
59+
qrData: _selectedOption! == context.loc.arkReceiveSegmentBoarding
60+
? btcAddress
61+
: arkAddress,
6362
),
6463
const Gap(16),
6564
ArkCopyAddressSection(
@@ -87,13 +86,16 @@ class ReceiveQR extends StatelessWidget {
8786
padding: const EdgeInsets.all(16),
8887
constraints: const BoxConstraints(maxHeight: 300, maxWidth: 300),
8988
decoration: BoxDecoration(
90-
color: context.appColors.onPrimary,
89+
color: context.appColors.background,
9190
borderRadius: BorderRadius.circular(12),
9291
),
93-
child:
94-
qrData.isNotEmpty
95-
? QrImageView(data: qrData)
96-
: const LoadingBoxContent(height: 200),
92+
child: qrData.isNotEmpty
93+
? QrImageView(
94+
data: qrData,
95+
// ignore: deprecated_member_use
96+
foregroundColor: context.appColors.secondary,
97+
)
98+
: const LoadingBoxContent(height: 200),
9799
),
98100
);
99101
}
@@ -120,12 +122,12 @@ class _ArkCopyAddressSectionState extends State<ArkCopyAddressSection> {
120122
Widget build(BuildContext context) {
121123
final currentAddress =
122124
widget.selectedOption == context.loc.arkReceiveSegmentBoarding
123-
? widget.btcAddress
124-
: widget.arkAddress;
125+
? widget.btcAddress
126+
: widget.arkAddress;
125127
final addressLabel =
126128
widget.selectedOption == context.loc.arkReceiveSegmentBoarding
127-
? context.loc.arkReceiveBoardingAddress
128-
: context.loc.arkArkAddress;
129+
? context.loc.arkReceiveBoardingAddress
130+
: context.loc.arkArkAddress;
129131

130132
return Padding(
131133
padding: const EdgeInsets.symmetric(horizontal: 16),
@@ -140,13 +142,12 @@ class _ArkCopyAddressSectionState extends State<ArkCopyAddressSection> {
140142
overflow: .ellipsis,
141143
canShowValueModal: true,
142144
modalTitle: addressLabel,
143-
modalContent:
144-
currentAddress
145-
.replaceAllMapped(
146-
RegExp('.{1,4}'),
147-
(match) => '${match.group(0)} ',
148-
)
149-
.trim(),
145+
modalContent: currentAddress
146+
.replaceAllMapped(
147+
RegExp('.{1,4}'),
148+
(match) => '${match.group(0)} ',
149+
)
150+
.trim(),
150151
),
151152
],
152153
),

0 commit comments

Comments
 (0)