Files
hash-wallet/cw_core/lib/root_dir.dart
T
jwinterm 16c4d3b128 Hardcoded appName cake_wallet -> hash_wallet + nuke changelog modal + Wownero up top
Three semi-independent fixes flagged from a user-facing testing pass:

1. cw_core/lib/root_dir.dart had a hardcoded 'cake_wallet' for the
   Linux app data dir, bypassing the binary name entirely. That's why
   ~/.config/cake_wallet/ kept being created even after the project
   rename. Changed appName const to hash_wallet. Also:
   - CAKE_WALLET_DIR env-var override -> HASH_WALLET_DIR (with the
     old name kept as a fallback so users migrating from a Cake
     install via env-var don't lose their path).
   - linuxSymlinkSharedPreferences kept the legacy
     ['com.example.cake_wallet','cake_wallet'] paths in the migration
     array so existing Cake users get auto-migrated into hash_wallet's
     new home on first launch of the fork.

2. lib/new-ui/new_dashboard.dart: commented out the
   Future.delayed(300ms).then(_showChangelog) trigger. The changelog
   content lives under assets/new-ui/changelog/text and describes
   Cake's v6.1.0 release notes — not ours. The 'View more info' button
   inside the modal launched blog.cakewallet.com. Re-enable once we
   write our own changelog content.

3. tool/configure.dart: WalletType.wownero hoisted to the top of the
   generated availableWalletTypes list. It's the reason this fork
   exists, so it should be the first choice in create / restore
   pickers. Monero stays as #2.
2026-05-16 19:04:45 -04:00

136 lines
5.1 KiB
Dart

import 'dart:io';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
String? _rootDirPath;
const String _tailsData = '/live/persistence/TailsData_unlocked/Persistent';
bool get isNonAmnesticTails {
try {
final os = File("/etc/os-release").readAsLinesSync();
for (var line in os) {
if (!line.startsWith("ID=")) continue;
if (!line.contains("tails")) continue;
return Directory(_tailsData).existsSync();
}
} catch (e) {
return false;
}
return false;
}
bool showNotice = true;
void setRootDirFromEnv() =>
// HASH_WALLET_DIR is the canonical override; CAKE_WALLET_DIR kept as a
// fallback so users migrating from a Cake install via env-var override
// don't lose their path.
_rootDirPath = Platform.environment['HASH_WALLET_DIR'] ?? Platform.environment['CAKE_WALLET_DIR'];
void copyDirectory(Directory source, Directory destination) {
source.listSync(recursive: false).forEach((var entity) {
if (entity is Directory) {
var newDirectory = Directory(p.join(destination.absolute.path, p.basename(entity.path)));
newDirectory.createSync(recursive: true);
copyDirectory(entity.absolute, newDirectory);
} else if (entity is File) {
destination.createSync(recursive: true);
entity.copySync(p.join(destination.path, p.basename(entity.path)));
}
});
}
Future<void> linuxSymlinkSharedPreferences() async {
if (!Platform.isLinux) return; // nuh-uh
final dataHome = Platform.environment["XDG_DATA_HOME"] ?? p.join(Platform.environment["HOME"] ?? "", ".local", "share");
// Names to migrate from on startup. Includes the legacy Cake paths so users
// forking from a previous Cake install get their data automatically
// symlinked into Hash Wallet's new home (~/.local/share/hash_wallet).
var legacyNames = ['com.example.cake_wallet', 'cake_wallet'];
for (String name in legacyNames) {
final oldPath = p.join(dataHome, name);
final newPath = p.join((await getAppDir()).path, "_local_share");
final oldDir = Directory(oldPath);
final oldLink = Link(oldPath);
final newDir = Directory(newPath);
if (oldDir.existsSync()) {
if (oldLink.existsSync()) {
printV("not creating, link exists");
} else {
if (newDir.existsSync()) {
newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch~/1000}");
}
copyDirectory(oldDir, newDir);
oldDir.deleteSync(recursive: true);
}
}
if (!oldLink.existsSync()) {
oldLink.create(newPath, recursive: true);
}
if (!newDir.existsSync()) {
newDir.createSync(recursive: true);
}
}
}
Future<Directory> getAppDir() async {
const String appName = 'hash_wallet';
Directory dir;
if (_rootDirPath != null && _rootDirPath!.isNotEmpty) {
dir = Directory.fromUri(Uri.file(_rootDirPath!));
dir.create(recursive: true);
} else {
if (Platform.isWindows) {
dir = await getApplicationSupportDirectory();
} else if (Platform.isLinux) {
String? appDirPath;
try {
dir = await getApplicationDocumentsDirectory();
appDirPath = '${dir.path}/$appName';
} catch (e) {
appDirPath = null;
}
// App will try to use last entry in here, so {distro,package}-specific paths can be
// be put as one of last items (tails - I'm looking at you), and other paths can be
// added in the order of preference
// Which currently is $HOME/.config/$appName - as this is the most standard directory
// for storing things that users in general back-up
var linuxAppPath = [
if (appDirPath != null) appDirPath, // old preferred
p.join('/home', Platform.environment['USER']??"null", appName), // old fallback
if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
if (isNonAmnesticTails) p.join(_tailsData, ".$appName") // tails (if persistance is enabled)
];
String preferredPath = linuxAppPath.last;
preferredLoop:
for (String notSoPreferredPath in linuxAppPath) {
if (notSoPreferredPath == linuxAppPath.last) continue;
bool useThisOne = Directory(notSoPreferredPath).existsSync();
if (useThisOne) {
if (showNotice) {
showNotice = false;
printV("Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
printV("Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
printV("Or use CAKE_WALLET_DIR=/path/to/app/ ${Platform.executable}");
}
preferredPath = notSoPreferredPath;
break preferredLoop;
}
}
dir = Directory.fromUri(Uri.file(preferredPath));
await dir.create(recursive: true);
} else {
dir = await getApplicationDocumentsDirectory();
}
}
return dir;
}