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();