linux fixes (#3262)
* linux fixes fix: use ints instead of bools in SQLite to prevent crashes on linux fix: disable lightning if it's unsupported ui: start linux app in portrait mode instead of landscape so it looks nicer * minor cleanup --------- Co-authored-by: Omar <omarh.ismail1@gmail.com>
cyan committed
May 28, 2026 at 17:10 UTC
8979811de7c6c3e6f2e35b44f447dba9d5f57059
5 files changed
+47
-34
cw_bitcoin/lib/electrum_wallet.dart
+9
-2
@@ -4,6 +4,7 @@ import 'dart:io';
4
import 'dart:isolate';
5
6
import 'package:bitcoin_base/bitcoin_base.dart';
7
+import 'package:cw_bitcoin/lightning/lightning_wallet.dart';
8
import 'package:cw_core/hardware/hardware_wallet_service.dart';
9
import 'package:cw_core/root_dir.dart';
10
import 'package:cw_core/utils/proxy_wrapper.dart';
@@ -76,7 +77,7 @@ abstract class ElectrumWalletBase
77
ElectrumBalance? initialBalance,
78
CryptoCurrency? currency,
79
bool? alwaysScan,
79
- this.useLightning = true,
80
+ bool useLightning = true,
81
}) : _masterHD = getMasterHD(seedBytes, network, walletInfo.hardwareWalletType),
82
accountHD = getAccountHDWallet(
83
currency, network, seedBytes, xpub, derivationInfo, walletInfo.hardwareWalletType),
@@ -102,6 +103,7 @@ abstract class ElectrumWalletBase
103
this.unspentCoinsInfo = unspentCoinsInfo,
104
this.isTestnet = !network.isMainnet,
105
this._mnemonic = mnemonic,
106
+ _useLightning = useLightning,
107
super(walletInfo, derivationInfo) {
108
this.electrumClient = electrumClient ?? electrum.ElectrumClient();
109
this.walletInfo = walletInfo;
@@ -305,8 +307,13 @@ abstract class ElectrumWalletBase
307
@observable
308
bool? alwaysScan;
309
310
+ @computed
311
+ bool get useLightning => _useLightning && LightningWallet.isAvailable;
312
+
313
+ set useLightning(bool val) => _useLightning = val && LightningWallet.isAvailable;
314
+
315
@observable
309
- bool useLightning;
316
+ bool _useLightning;
317
318
final Bip32Slip10Secp256k1? _masterHD;
319
final Bip32Slip10Secp256k1 accountHD;
cw_core/lib/node.dart
+35
-25
@@ -92,15 +92,25 @@ class Node {
92
login = map['login'] as String?,
93
label = map['label'] as String?,
94
password = map['password'] as String?,
95
- isPow = (map["isPow"] != null && map['isPow'] != 0) as bool? ?? false,
96
- useSSL = (map['useSSL'] != 0) as bool?,
95
+ isPow = _getBoolFromDB(map['isPow']),
96
+ useSSL = _getBoolFromDB(map['useSSL']),
97
typeRaw = (map["typeRaw"] ?? 0) as int,
98
- trusted = (map['trusted'] != 0) as bool? ?? false,
98
+ trusted = _getBoolFromDB(map['trusted']),
99
socksProxyAddress = map['socksProxyAddress'] as String?,
100
- isEnabledForAutoSwitching = (map['isEnabledForAutoSwitching'] != 0) as bool? ?? false,
101
- isOfficial = (map['isOfficial'] != 0) as bool? ?? false,
102
- isBuiltin = (map['isBuiltin'] != 0) as bool? ?? false,
103
- isDefault = (map['isDefault'] != 0) as bool? ?? false;
100
+ isEnabledForAutoSwitching = _getBoolFromDB(map['isEnabledForAutoSwitching']),
101
+ isOfficial = _getBoolFromDB(map['isOfficial']),
102
+ isBuiltin = _getBoolFromDB(map['isBuiltin']),
103
+ isDefault = _getBoolFromDB(map['isDefault']);
104
+
105
+ static bool _getBoolFromDB(value, {bool? defaultValue}) {
106
+ if (value is bool) {
107
+ return value;
108
+ } else if (value is int) {
109
+ return value == 1;
110
+ } else {
111
+ return defaultValue ?? false;
112
+ }
113
+ }
114
115
Map<String, dynamic> toMap() {
116
return {
@@ -110,15 +120,15 @@ class Node {
120
'login': login,
121
"label": label,
122
'password': password,
113
- "isPow": isPow,
114
- 'useSSL': useSSL,
123
+ "isPow": isPow ? 1 : 0,
124
+ 'useSSL': (useSSL??false) ? 1 : 0,
125
"typeRaw": typeRaw,
116
- 'trusted': trusted,
126
+ 'trusted': trusted ? 1 : 0,
127
'socksProxyAddress': socksProxyAddress,
118
- 'isEnabledForAutoSwitching': isEnabledForAutoSwitching,
119
- "isOfficial": isOfficial,
120
- "isBuiltin": isBuiltin,
121
- "isDefault": isDefault
128
+ 'isEnabledForAutoSwitching': isEnabledForAutoSwitching ? 1 : 0,
129
+ "isOfficial": isOfficial ? 1 : 0,
130
+ "isBuiltin": isBuiltin ? 1 : 0,
131
+ "isDefault": isDefault ? 1 : 0
132
};
133
}
134
@@ -127,11 +137,11 @@ class Node {
137
}
138
139
static Future<int> deleteAll() async {
130
- return await db!.delete(tableName, where: "isPow = ?", whereArgs: [false]);
140
+ return await db!.delete(tableName, where: "isPow = ?", whereArgs: [0]);
141
}
142
143
static Future<int> deleteAllPow() async {
134
- return await db!.delete(tableName, where: "isPow = ?", whereArgs: [true]);
144
+ return await db!.delete(tableName, where: "isPow = ?", whereArgs: [1]);
145
}
146
147
Future<int> save() async {
@@ -173,35 +183,35 @@ class Node {
183
184
185
static Future<List<Node>> getAll() async {
176
- return selectList("isPow = ?", [false]);
186
+ return selectList("isPow = ?", [0]);
187
}
188
189
static Future<List<Node>> getAllBuiltin() async {
180
- return selectList("isPow = ? AND isBuiltin = ?", [false, true]);
190
+ return selectList("isPow = ? AND isBuiltin = ?", [0, 1]);
191
}
192
193
static Future<List<Node>> getAllPowBuiltin() async {
184
- return selectList("isPow = ? AND isBuiltin = ?", [true, true]);
194
+ return selectList("isPow = ? AND isBuiltin = ?", [1, 1]);
195
}
196
197
static Future<List<Node>> getAllForWalletType(WalletType type) async {
188
- return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), false]);
198
+ return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), 0]);
199
}
200
201
static Future<Node?> getDefaultForWalletType(WalletType type) async {
192
- return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), false, true])).firstOrNull;
202
+ return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1])).firstOrNull;
203
}
204
205
static Future<Node?> getDefaultPowForWalletType(WalletType type) async {
196
- return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), true, true])).firstOrNull;
206
+ return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1])).firstOrNull;
207
}
208
209
static Future<List<Node>> getAllForWalletTypePow(WalletType type) async {
200
- return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), true]);
210
+ return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), 1]);
211
}
212
213
static Future<List<Node>> getAllPow() async {
204
- return selectList("isPow = ?", [true]);
214
+ return selectList("isPow = ?", [1]);
215
}
216
217
static Future<Node?> get(int id) async {
@@ -475,7 +485,7 @@ class Node {
485
},
486
),
487
);
478
-
488
+
489
final data = jsonDecode(response.body);
490
if (response.statusCode != 200 ||
491
data["error"] != null ||
lib/new-ui/pages/receive_page.dart
+1
-1
@@ -342,7 +342,7 @@ class _NewReceivePageState extends State<NewReceivePage> {
342
setState(() {
343
_addressItemWithLabel = widget.addressListViewModel.forceRecomputeItems.firstWhereOrNull(
344
(item) => (item is WalletAddressListItem && item.address == newAddress.address))
345
- as WalletAddressListItem;
345
+ as WalletAddressListItem?;
346
});
347
}
348
}
lib/new-ui/pages/send_page.dart
+1
-1
@@ -972,7 +972,7 @@ class _NewSendPageState extends State<NewSendPage> {
972
onNext: (PaymentFlowResult newResult) {
973
final selectedChainId = newResult.chainId;
974
final isCompatible =
975
- selectedChainId == evm!.getSelectedChainId(widget.sendViewModel.wallet);
975
+ selectedChainId == evm?.getSelectedChainId(widget.sendViewModel.wallet);
976
977
if (isCompatible) {
978
widget.sendViewModel.setSelectedCryptoCurrency(
linux/my_application.cc
+1
-5
@@ -46,11 +46,7 @@ static void my_application_activate(GApplication* application) {
46
} else {
47
gtk_window_set_title(window, "Cake Wallet");
48
}
49
- if (getenv("DESKTOP_FORCE_MOBILE")) {
50
- gtk_window_set_default_size(window, 720, 1280);
51
- } else {
52
- gtk_window_set_default_size(window, 1280, 720);
53
- }
49
+ gtk_window_set_default_size(window, 480, 800);
50
gtk_widget_show(GTK_WIDGET(window));
51
52
g_autoptr(FlDartProject) project = fl_dart_project_new();