mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
Audit of every surface that could show somebody else's logo. Most of it was already ours: the transaction success screen draws hash_bag.png and the hashbag_sym_* glyphs, cake_logo_light/dark.svg and the Android icon set were redrawn from the Hash Bags mark in May and only kept their old filenames, no user-visible string contains "Cake", and every cupcake reference is a HardwareWalletType icon sitting next to Ledger and Trezor, which is interop rather than branding. Two places were not ours. The Flatpak manifest installed cakewallet_icon_180.png as the Linux desktop icon, and that file is upstream Cake artwork from 2025 that the rebrand never touched. So the Linux build has been shipping a Cake Wallet icon. It now uses the Hash Bags mark. The macOS icon script had the same fault, latent only because no workflow builds macOS; it gets a proper Hash Bags set at all seven sizes rather than a landmine for whoever turns that build on. Deleted the Cake artwork nothing needs: cake_logo.png, cakepay.png, the three cakewallet_icon_* files and the macOS set. assets/images/ is bundled whole, so unreferenced files were shipping inside the binary regardless of whether any code could draw them. Also fixes a bug the audit turned up rather than a branding one. The theme picker chose its preview icon by matching theme.title, which is built from the accent colour's display name, so renaming an accent silently changed the icon. It had: the list still named Cake Primary, Tron Red and Frosting Purple, none of which ship, while our own Such Pink and Such Blue were absent and fell through to the plain dark icon. It asks the theme what it is now, not what it is called. Version to 1.0.3+13. pubspec_description.yaml is the single source for all five platforms; the checked-in pubspec.yaml is a build artifact. Still there, reported not removed: cake_pay_icon.png, reachable only through the Cake Pay order provider, which is the only provider, has an empty API key and cannot produce an order in this app. Removing it means removing the orders feature, which is not a branding change.
266 lines
8.6 KiB
Dart
266 lines
8.6 KiB
Dart
import 'package:hash_wallet/entities/balance_display_mode.dart';
|
|
import 'package:hash_wallet/entities/bitcoin_amount_display_mode.dart';
|
|
import 'package:hash_wallet/entities/fiat_currency.dart';
|
|
import 'package:hash_wallet/entities/sync_status_display_mode.dart';
|
|
import 'package:hash_wallet/store/app_store.dart';
|
|
import 'package:hash_wallet/store/settings_store.dart';
|
|
import 'package:hash_wallet/themes/core/material_base_theme.dart';
|
|
import 'package:hash_wallet/themes/theme_classes/black_theme.dart';
|
|
import 'package:hash_wallet/themes/utils/theme_list.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
import 'package:mobx/mobx.dart';
|
|
import 'package:hash_wallet/entities/fiat_api_mode.dart';
|
|
import 'package:hash_wallet/themes/core/theme_store.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
part 'display_settings_view_model.g.dart';
|
|
|
|
class DisplaySettingsViewModel = DisplaySettingsViewModelBase with _$DisplaySettingsViewModel;
|
|
|
|
abstract class DisplaySettingsViewModelBase with Store {
|
|
DisplaySettingsViewModelBase(this._appStore, this._themeStore);
|
|
|
|
final AppStore _appStore;
|
|
SettingsStore get _settingsStore => _appStore.settingsStore;
|
|
final ThemeStore _themeStore;
|
|
|
|
@computed
|
|
bool get disableTradeOption => _settingsStore.disableTradeOption;
|
|
|
|
@computed
|
|
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
|
|
|
|
@computed
|
|
String get languageCode => _settingsStore.languageCode;
|
|
|
|
@computed
|
|
BalanceDisplayMode get balanceDisplayMode => _settingsStore.balanceDisplayMode;
|
|
|
|
@computed
|
|
bool get shouldDisplayBalance => balanceDisplayMode == BalanceDisplayMode.displayableBalance;
|
|
|
|
@computed
|
|
bool get shouldShowMarketPlaceInDashboard => _settingsStore.shouldShowMarketPlaceInDashboard;
|
|
|
|
@computed
|
|
BitcoinAmountDisplayMode get displayAmountsInSatoshi => _settingsStore.displayAmountsInSatoshi;
|
|
|
|
@computed
|
|
MaterialThemeBase get currentTheme => _themeStore.currentTheme;
|
|
|
|
@computed
|
|
ThemeMode get themeMode => _themeStore.themeMode;
|
|
|
|
@computed
|
|
bool get isBlackThemeOledEnabled => _themeStore.currentTheme is BlackTheme && _themeStore.isOled;
|
|
|
|
@computed
|
|
bool get disabledFiatApiMode => _settingsStore.fiatApiMode == FiatApiMode.disabled;
|
|
|
|
@computed
|
|
bool get showAddressBookPopup => _settingsStore.showAddressBookPopupEnabled;
|
|
|
|
@computed
|
|
bool get showZcashCard => _settingsStore.showZcashMissingFundsCard;
|
|
|
|
@computed
|
|
SyncStatusDisplayMode get syncStatusDisplayMode => _settingsStore.syncStatusDisplayMode;
|
|
|
|
@computed
|
|
String get backgroundImage => _settingsStore.backgroundImage;
|
|
|
|
@computed
|
|
List<MaterialThemeBase> get availableThemes {
|
|
List<MaterialThemeBase> themes;
|
|
switch (themeMode) {
|
|
case ThemeMode.light:
|
|
themes = ThemeList.all.where((theme) => theme.brightness == Brightness.light).toList();
|
|
break;
|
|
case ThemeMode.dark:
|
|
themes = ThemeList.all.where((theme) => theme.brightness == Brightness.dark).toList();
|
|
break;
|
|
case ThemeMode.system:
|
|
final systemBrightness = WidgetsBinding.instance.platformDispatcher.platformBrightness;
|
|
themes = ThemeList.all.where((theme) => theme.brightness == systemBrightness).toList();
|
|
break;
|
|
}
|
|
|
|
List<MaterialThemeBase> groupedThemes = [];
|
|
Set<String> addedThemeFamilies = {};
|
|
|
|
for (final theme in themes) {
|
|
if (theme.hasAccentColors) {
|
|
final family = theme.themeFamily!;
|
|
if (!addedThemeFamilies.contains(family)) {
|
|
groupedThemes.add(theme);
|
|
addedThemeFamilies.add(family);
|
|
}
|
|
} else {
|
|
groupedThemes.add(theme);
|
|
}
|
|
}
|
|
|
|
return groupedThemes;
|
|
}
|
|
|
|
@computed
|
|
List<ThemeAccentColor> get availableAccentColors {
|
|
if (!currentTheme.hasAccentColors) return [];
|
|
|
|
if (currentTheme.themeFamily == 'BlackTheme') {
|
|
return BlackThemeAccentColor.values;
|
|
}
|
|
return [];
|
|
}
|
|
|
|
@action
|
|
void setDisableTradeOption(bool value) => _settingsStore.disableTradeOption = value;
|
|
|
|
@action
|
|
void setBalanceDisplayMode(BalanceDisplayMode value) => _settingsStore.balanceDisplayMode = value;
|
|
|
|
@computed
|
|
bool get showDisplayAmountsInSatoshiSetting => _appStore.wallet?.type == WalletType.bitcoin;
|
|
|
|
@computed
|
|
bool get showZcashCardSetting => false;
|
|
|
|
@action
|
|
void setDisplayAmountsInSatoshi(BitcoinAmountDisplayMode value) => _settingsStore.displayAmountsInSatoshi = value;
|
|
|
|
@action
|
|
void setShowZcashCard(bool value) => _settingsStore.showZcashMissingFundsCard = value;
|
|
|
|
@action
|
|
void setShouldDisplayBalance(bool value) {
|
|
if (value) {
|
|
_settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance;
|
|
} else {
|
|
_settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance;
|
|
}
|
|
}
|
|
|
|
@action
|
|
void onLanguageSelected(String code) {
|
|
_settingsStore.languageCode = code;
|
|
}
|
|
|
|
@action
|
|
Future<void> onThemeSelected(MaterialThemeBase newTheme) async {
|
|
if (newTheme is BlackTheme && _themeStore.isOled) {
|
|
await setTheme(BlackTheme(newTheme.accentColor, isOled: true));
|
|
return;
|
|
}
|
|
await setTheme(newTheme);
|
|
}
|
|
|
|
@action
|
|
Future<void> onAccentColorSelected(String accentColorId) async {
|
|
if (!currentTheme.hasAccentColors) return;
|
|
|
|
try {
|
|
final newTheme = ThemeList.all.firstWhere(
|
|
(theme) =>
|
|
theme.hasAccentColors &&
|
|
theme.themeFamily == currentTheme.themeFamily &&
|
|
theme.accentColorId == accentColorId,
|
|
);
|
|
|
|
if (newTheme != currentTheme) {
|
|
if (newTheme is BlackTheme && _themeStore.isOled) {
|
|
await onThemeSelected(BlackTheme(newTheme.accentColor, isOled: true));
|
|
} else {
|
|
await onThemeSelected(newTheme);
|
|
}
|
|
}
|
|
} catch (_) {}
|
|
}
|
|
|
|
@action
|
|
Future<void> setBlackThemeOled(bool value) async {
|
|
if (_themeStore.currentTheme is BlackTheme) {
|
|
await _themeStore.setOledEnabled(value);
|
|
}
|
|
}
|
|
|
|
bool isThemeSelected(MaterialThemeBase theme) {
|
|
if (!theme.hasAccentColors) return currentTheme == theme;
|
|
|
|
return currentTheme.hasAccentColors && currentTheme.themeFamily == theme.themeFamily;
|
|
}
|
|
|
|
bool isAccentColorSelected(String accentColorId) {
|
|
if (!currentTheme.hasAccentColors) return false;
|
|
|
|
return currentTheme.accentColorId == accentColorId;
|
|
}
|
|
|
|
@action
|
|
Future<void> setTheme(MaterialThemeBase newTheme) async {
|
|
await _themeStore.setTheme(newTheme);
|
|
}
|
|
|
|
MaterialThemeBase? getFirstMatchingTheme(ThemeMode mode) {
|
|
List<MaterialThemeBase> themes;
|
|
switch (mode) {
|
|
case ThemeMode.light:
|
|
themes = ThemeList.all.where((theme) => theme.brightness == Brightness.light).toList();
|
|
break;
|
|
case ThemeMode.dark:
|
|
themes = ThemeList.all.where((theme) => theme.brightness == Brightness.dark).toList();
|
|
break;
|
|
case ThemeMode.system:
|
|
final systemBrightness = WidgetsBinding.instance.platformDispatcher.platformBrightness;
|
|
themes = ThemeList.all.where((theme) => theme.brightness == systemBrightness).toList();
|
|
break;
|
|
}
|
|
|
|
return themes.isNotEmpty ? themes.first : null;
|
|
}
|
|
|
|
@action
|
|
Future<void> setThemeMode(ThemeMode value) async {
|
|
await _themeStore.setThemeMode(value);
|
|
// We won't override the saved custom theme when switching to system mode.
|
|
// We'll just let the ThemeStore resolve it based on system brightness and saved theme.
|
|
if (value != ThemeMode.system) {
|
|
final matchingTheme = getFirstMatchingTheme(value);
|
|
if (matchingTheme != null) {
|
|
await setTheme(matchingTheme);
|
|
}
|
|
}
|
|
}
|
|
|
|
@action
|
|
void setFiatCurrency(FiatCurrency value) => _settingsStore.fiatCurrency = value;
|
|
|
|
@action
|
|
void setShouldShowMarketPlaceInDashbaord(bool value) {
|
|
_settingsStore.shouldShowMarketPlaceInDashboard = value;
|
|
}
|
|
|
|
@action
|
|
void setShowAddressBookPopup(bool value) => _settingsStore.showAddressBookPopupEnabled = value;
|
|
|
|
@action
|
|
void setSyncStatusDisplayMode(SyncStatusDisplayMode value) =>
|
|
_settingsStore.syncStatusDisplayMode = value;
|
|
|
|
@action
|
|
void setBackgroundImage(String path) => _settingsStore.backgroundImage = path;
|
|
|
|
/// Preview icon for the theme picker.
|
|
///
|
|
/// This matched on `theme.title`, which is built from the accent colour's
|
|
/// display name, so renaming an accent silently changed which icon a theme
|
|
/// got. It did: the list still named Cake Primary, Tron Red and Frosting
|
|
/// Purple, none of which ship any more, while Such Pink and Such Blue were
|
|
/// absent and fell through to the plain dark icon. Ask the theme what it is
|
|
/// instead of what it is called.
|
|
String getImageForTheme(MaterialThemeBase theme) {
|
|
if (theme is BlackTheme) return 'assets/new-ui/black_accent.svg';
|
|
if (theme.type == ThemeType.light) return 'assets/new-ui/light.svg';
|
|
return 'assets/new-ui/dark.svg';
|
|
}
|
|
}
|