Skip to content

Commit 66aeed3

Browse files
committed
feat(tor): persist transport preferences
1 parent 4d5e032 commit 66aeed3

21 files changed

Lines changed: 630 additions & 68 deletions

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
lib/core/storage/schemas/**/drift_schema_v*.json linguist-generated
2+
lib/core/storage/*.steps.dart linguist-generated
3+
test/migrations_test/**/generated/*.dart linguist-generated

lib/core/core_locator.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import 'package:bb_mobile/core/ledger/ledger_locator.dart';
99
import 'package:bb_mobile/core/mempool/mempool_locator.dart';
1010
import 'package:bb_mobile/core/recoverbull/recoverbull_locator.dart';
1111
import 'package:bb_mobile/core/seed/seed_locator.dart';
12+
import 'package:bb_mobile/core/settings/domain/repositories/settings_repository.dart'
13+
as settings;
1214
import 'package:bb_mobile/core/settings/settings_locator.dart';
1315
import 'package:bb_mobile/core/storage/sqlite_database.dart';
1416
import 'package:bb_mobile/core/storage/storage_locator.dart';
@@ -55,7 +57,25 @@ class CoreLocator {
5557
}
5658

5759
static Future<void> registerRepositories(GetIt locator) async {
58-
bull_tor.TorLocator.registerRepositories(locator);
60+
await SettingsLocator.registerRepositories(locator);
61+
final settingsRepository = locator<settings.SettingsRepository>();
62+
final appSettings = await settingsRepository.fetch();
63+
bull_tor.TorLocator.registerRepositories(
64+
locator,
65+
initialMode: appSettings.torTransportMode,
66+
lastSuccessfulTransport: appSettings.lastSuccessfulTorTransport,
67+
onSuccessfulTransport: (transport) async {
68+
try {
69+
await settingsRepository.setLastSuccessfulTorTransport(transport);
70+
} catch (error, stackTrace) {
71+
log.warning(
72+
'Could not persist the successful Tor transport',
73+
error: error,
74+
trace: stackTrace,
75+
);
76+
}
77+
},
78+
);
5979
BlockchainLocator.registerRepositories(locator);
6080
ElectrumLocator.registerRepositories(locator);
6181
ExchangeLocator.registerRepositories(locator);

lib/core/settings/data/settings_datasource.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:bb_mobile/core/settings/data/settings_model.dart';
22
import 'package:bb_mobile/core/settings/domain/settings_entity.dart';
33
import 'package:bb_mobile/core/storage/sqlite_database.dart';
44
import 'package:drift/drift.dart';
5+
import 'package:bull_tor/tor.dart';
56

67
class SettingsDatasource {
78
final SqliteDatabase _sqlite;
@@ -73,6 +74,21 @@ class SettingsDatasource {
7374
);
7475
}
7576

77+
Future<void> setTorTransportMode(TorTransportMode mode) async {
78+
await _sqlite.managers.settings.update(
79+
(f) => f(id: const Value(1), torTransportMode: Value(mode.name)),
80+
);
81+
}
82+
83+
Future<void> setLastSuccessfulTorTransport(TorTransport transport) async {
84+
await _sqlite.managers.settings.update(
85+
(f) => f(
86+
id: const Value(1),
87+
lastSuccessfulTorTransport: Value(transport.name),
88+
),
89+
);
90+
}
91+
7692
Future<void> setThemeMode(AppThemeMode themeMode) async {
7793
await _sqlite.managers.settings.update(
7894
(f) => f(id: const Value(1), themeMode: Value(themeMode.name)),

lib/core/settings/data/settings_model.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:bb_mobile/core/settings/domain/settings_entity.dart';
22
import 'package:bb_mobile/core/storage/sqlite_database.dart';
3+
import 'package:bull_tor/tor.dart';
34

45
class SettingsModel {
56
final int id;
@@ -12,6 +13,8 @@ class SettingsModel {
1213
final bool isDevModeEnabled;
1314
final bool useTorProxy;
1415
final int torProxyPort;
16+
final TorTransportMode torTransportMode;
17+
final TorTransport? lastSuccessfulTorTransport;
1518
final AppThemeMode themeMode;
1619
final bool isErrorReportingEnabled;
1720
final String? exchangeTestnetBasicAuthUsername;
@@ -28,6 +31,8 @@ class SettingsModel {
2831
required this.isDevModeEnabled,
2932
required this.useTorProxy,
3033
required this.torProxyPort,
34+
required this.torTransportMode,
35+
this.lastSuccessfulTorTransport,
3136
required this.themeMode,
3237
required this.isErrorReportingEnabled,
3338
this.exchangeTestnetBasicAuthUsername,
@@ -46,6 +51,8 @@ class SettingsModel {
4651
isDevModeEnabled: isDevModeEnabled,
4752
useTorProxy: useTorProxy,
4853
torProxyPort: torProxyPort,
54+
torTransportMode: torTransportMode.name,
55+
lastSuccessfulTorTransport: lastSuccessfulTorTransport?.name,
4956
themeMode: themeMode.name,
5057
isErrorReportingEnabled: isErrorReportingEnabled,
5158
exchangeTestnetBasicAuthUsername: exchangeTestnetBasicAuthUsername,
@@ -65,6 +72,15 @@ class SettingsModel {
6572
isDevModeEnabled: row.isDevModeEnabled,
6673
useTorProxy: row.useTorProxy,
6774
torProxyPort: row.torProxyPort,
75+
torTransportMode: TorTransportMode.values.firstWhere(
76+
(mode) => mode.name == row.torTransportMode,
77+
orElse: () => TorTransportMode.automatic,
78+
),
79+
lastSuccessfulTorTransport: switch (row.lastSuccessfulTorTransport) {
80+
'direct' => TorTransport.direct,
81+
'snowflake' => TorTransport.snowflake,
82+
_ => null,
83+
},
6884
themeMode: AppThemeMode.fromName(row.themeMode),
6985
isErrorReportingEnabled: row.isErrorReportingEnabled,
7086
exchangeTestnetBasicAuthUsername: row.exchangeTestnetBasicAuthUsername,

lib/core/settings/data/settings_repository.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:bb_mobile/core/settings/domain/repositories/settings_repository.
66
as domain;
77
import 'package:bb_mobile/core/settings/domain/settings_entity.dart';
88
import 'package:bb_mobile/core/utils/report.dart';
9+
import 'package:bull_tor/tor.dart';
910

1011
class SettingsRepository implements domain.SettingsRepository {
1112
final SettingsDatasource _settingsDatasource;
@@ -34,6 +35,8 @@ class SettingsRepository implements domain.SettingsRepository {
3435
required bool isDevModeEnabled,
3536
required bool useTorProxy,
3637
required int torProxyPort,
38+
TorTransportMode torTransportMode = TorTransportMode.automatic,
39+
TorTransport? lastSuccessfulTorTransport,
3740
AppThemeMode themeMode = AppThemeMode.system,
3841
bool isErrorReportingEnabled = false,
3942
String? exchangeTestnetBasicAuthUsername,
@@ -51,6 +54,8 @@ class SettingsRepository implements domain.SettingsRepository {
5154
isDevModeEnabled: isDevModeEnabled,
5255
useTorProxy: useTorProxy,
5356
torProxyPort: torProxyPort,
57+
torTransportMode: torTransportMode,
58+
lastSuccessfulTorTransport: lastSuccessfulTorTransport,
5459
themeMode: themeMode,
5560
isErrorReportingEnabled: isErrorReportingEnabled,
5661
exchangeTestnetBasicAuthUsername: exchangeTestnetBasicAuthUsername,
@@ -73,6 +78,8 @@ class SettingsRepository implements domain.SettingsRepository {
7378
isDevModeEnabled: s.isDevModeEnabled,
7479
useTorProxy: s.useTorProxy,
7580
torProxyPort: s.torProxyPort,
81+
torTransportMode: s.torTransportMode,
82+
lastSuccessfulTorTransport: s.lastSuccessfulTorTransport,
7683
themeMode: s.themeMode,
7784
isErrorReportingEnabled: s.isErrorReportingEnabled,
7885
exchangeTestnetBasicAuthUsername: s.exchangeTestnetBasicAuthUsername,
@@ -126,6 +133,16 @@ class SettingsRepository implements domain.SettingsRepository {
126133
await _settingsDatasource.setTorProxyPort(port);
127134
}
128135

136+
@override
137+
Future<void> setTorTransportMode(TorTransportMode mode) async {
138+
await _settingsDatasource.setTorTransportMode(mode);
139+
}
140+
141+
@override
142+
Future<void> setLastSuccessfulTorTransport(TorTransport transport) async {
143+
await _settingsDatasource.setLastSuccessfulTorTransport(transport);
144+
}
145+
129146
@override
130147
Future<void> setThemeMode(AppThemeMode themeMode) async {
131148
await _settingsDatasource.setThemeMode(themeMode);

lib/core/settings/domain/repositories/settings_repository.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:async';
22

33
import 'package:bb_mobile/core/settings/domain/settings_entity.dart';
4+
import 'package:bull_tor/tor.dart';
45

56
abstract class SettingsRepository {
67
Stream<String> get currencyChangeStream;
@@ -18,6 +19,8 @@ abstract class SettingsRepository {
1819
required bool isDevModeEnabled,
1920
required bool useTorProxy,
2021
required int torProxyPort,
22+
TorTransportMode torTransportMode = TorTransportMode.automatic,
23+
TorTransport? lastSuccessfulTorTransport,
2124
AppThemeMode themeMode = AppThemeMode.system,
2225
bool isErrorReportingEnabled = false,
2326
String? exchangeTestnetBasicAuthUsername,
@@ -44,6 +47,10 @@ abstract class SettingsRepository {
4447

4548
Future<void> setTorProxyPort(int port);
4649

50+
Future<void> setTorTransportMode(TorTransportMode mode);
51+
52+
Future<void> setLastSuccessfulTorTransport(TorTransport transport);
53+
4754
Future<void> setThemeMode(AppThemeMode themeMode);
4855

4956
Future<void> setErrorReportingEnabled(bool enabled);

lib/core/settings/domain/settings_entity.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:ui';
33
import 'package:bb_mobile/core/utils/logger.dart';
44
import 'package:flutter/material.dart';
55
import 'package:freezed_annotation/freezed_annotation.dart';
6+
import 'package:bull_tor/tor.dart';
67

78
part 'settings_entity.freezed.dart';
89

@@ -141,6 +142,8 @@ abstract class SettingsEntity with _$SettingsEntity {
141142
bool? isDevModeEnabled,
142143
@Default(false) bool useTorProxy,
143144
@Default(9050) int torProxyPort,
145+
@Default(TorTransportMode.automatic) TorTransportMode torTransportMode,
146+
TorTransport? lastSuccessfulTorTransport,
144147
@Default(AppThemeMode.system) AppThemeMode themeMode,
145148
@Default(false) bool isErrorReportingEnabled,
146149
String? exchangeTestnetBasicAuthUsername,

lib/core/storage/database_seeds.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class DatabaseSeeds {
2121
isDevModeEnabled: false,
2222
useTorProxy: false,
2323
torProxyPort: 9050,
24+
torTransportMode: 'automatic',
2425
themeMode: 'system',
2526
isErrorReportingEnabled: false,
2627
),

lib/core/storage/migrations/schema_13_to_14.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ class Schema13To14 {
5959
() => m.createIndex(schema14.orderSwapsLocalPayinTxid),
6060
'order_swaps_local_payin_txid index',
6161
);
62+
63+
await _addColumnIfNotExists(
64+
() => m.addColumn(schema14.settings, schema14.settings.torTransportMode),
65+
'settings.tor_transport_mode column',
66+
);
67+
await _addColumnIfNotExists(
68+
() => m.addColumn(
69+
schema14.settings,
70+
schema14.settings.lastSuccessfulTorTransport,
71+
),
72+
'settings.last_successful_tor_transport column',
73+
);
6274
}
6375
}
6476

@@ -79,3 +91,18 @@ Future<void> _createIfNotExists(
7991
);
8092
}
8193
}
94+
95+
Future<void> _addColumnIfNotExists(
96+
Future<void> Function() addColumn,
97+
String description,
98+
) async {
99+
try {
100+
await addColumn();
101+
} catch (e) {
102+
if (!e.toString().contains('duplicate column name')) rethrow;
103+
log.warning(
104+
'Schema13To14: $description already exists — skipping add',
105+
error: e,
106+
);
107+
}
108+
}

lib/core/storage/schemas/bull_database/drift_schema_v14.json

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)