fix(wallet-switch): cluster C — no mis-scoping in the unknown-identity window
From the audit: while a switch/first-load is in flight the wallet identity hash is empty, so contact/portfolio scope-writes silently fell back to "global" (leaking a wallet-specific entry into every wallet) and scope-filters showed every wallet's scoped entries. - Contacts: a NEW wallet-scoped contact created while the identity is unknown is now refused with a clear message (tick global or wait); editing an existing scoped contact preserves its scope instead of demoting it to global. - Portfolio: the "Add group" button is disabled while the identity is unknown (with a tooltip), so a new group can't get an empty/global scope. - Both views' visibility filters now show ONLY global entries when the identity is unknown — never another wallet's scoped contacts/groups — instead of showing everything. - +2 i18n strings (8 langs; reworded one zh string to stay within the CJK subset). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "Ein: Dieser Kontakt bleibt sichtbar, egal welche Wallet Sie laden. Aus: Er gehört nur zur aktuellen Wallet.",
|
"contact_global_tt": "Ein: Dieser Kontakt bleibt sichtbar, egal welche Wallet Sie laden. Aus: Er gehört nur zur aktuellen Wallet.",
|
||||||
"contact_preview_addr": "Adresse erscheint hier",
|
"contact_preview_addr": "Adresse erscheint hier",
|
||||||
"contact_preview_name": "Kontaktname",
|
"contact_preview_name": "Kontaktname",
|
||||||
|
"contact_wallet_loading": "Die Wallet lädt noch — aktiviere „In jeder Wallet anzeigen“ oder versuche es gleich erneut.",
|
||||||
"contacts": "Kontakte",
|
"contacts": "Kontakte",
|
||||||
"contacts_search_no_match": "Keine passenden Kontakte",
|
"contacts_search_no_match": "Keine passenden Kontakte",
|
||||||
"contacts_search_placeholder": "Kontakte durchsuchen...",
|
"contacts_search_placeholder": "Kontakte durchsuchen...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "Hervorgehobene Zeilen",
|
"portfolio_style_featured": "Hervorgehobene Zeilen",
|
||||||
"portfolio_style_label": "Portfolio-Stil",
|
"portfolio_style_label": "Portfolio-Stil",
|
||||||
"portfolio_untitled": "Ohne Titel",
|
"portfolio_untitled": "Ohne Titel",
|
||||||
|
"portfolio_wallet_loading": "Warte, bis die Wallet fertig geladen ist, um eine Gruppe hinzuzufügen.",
|
||||||
"price_chart": "Preisdiagramm",
|
"price_chart": "Preisdiagramm",
|
||||||
"privacy_great": "Großartige Privatsphäre!",
|
"privacy_great": "Großartige Privatsphäre!",
|
||||||
"privacy_low": "Geringe Privatsphäre — Gelder abschirmen",
|
"privacy_low": "Geringe Privatsphäre — Gelder abschirmen",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "Activado: este contacto permanece visible sin importar qué cartera cargues. Desactivado: pertenece solo a la cartera actual.",
|
"contact_global_tt": "Activado: este contacto permanece visible sin importar qué cartera cargues. Desactivado: pertenece solo a la cartera actual.",
|
||||||
"contact_preview_addr": "La dirección aparecerá aquí",
|
"contact_preview_addr": "La dirección aparecerá aquí",
|
||||||
"contact_preview_name": "Nombre del contacto",
|
"contact_preview_name": "Nombre del contacto",
|
||||||
|
"contact_wallet_loading": "La cartera aún se está cargando: marca «Mostrar en todas las carteras» o inténtalo de nuevo en un momento.",
|
||||||
"contacts": "Contactos",
|
"contacts": "Contactos",
|
||||||
"contacts_search_no_match": "No hay contactos coincidentes",
|
"contacts_search_no_match": "No hay contactos coincidentes",
|
||||||
"contacts_search_placeholder": "Buscar contactos...",
|
"contacts_search_placeholder": "Buscar contactos...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "Filas destacadas",
|
"portfolio_style_featured": "Filas destacadas",
|
||||||
"portfolio_style_label": "Estilo de cartera",
|
"portfolio_style_label": "Estilo de cartera",
|
||||||
"portfolio_untitled": "Sin título",
|
"portfolio_untitled": "Sin título",
|
||||||
|
"portfolio_wallet_loading": "Espera a que la cartera termine de cargar para añadir un grupo.",
|
||||||
"price_chart": "Gráfico de Precios",
|
"price_chart": "Gráfico de Precios",
|
||||||
"privacy_great": "¡Excelente privacidad!",
|
"privacy_great": "¡Excelente privacidad!",
|
||||||
"privacy_low": "Privacidad baja: protege los fondos",
|
"privacy_low": "Privacidad baja: protege los fondos",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "Activé : ce contact reste visible quel que soit le portefeuille chargé. Désactivé : il appartient au portefeuille actuel uniquement.",
|
"contact_global_tt": "Activé : ce contact reste visible quel que soit le portefeuille chargé. Désactivé : il appartient au portefeuille actuel uniquement.",
|
||||||
"contact_preview_addr": "L'adresse apparaîtra ici",
|
"contact_preview_addr": "L'adresse apparaîtra ici",
|
||||||
"contact_preview_name": "Nom du contact",
|
"contact_preview_name": "Nom du contact",
|
||||||
|
"contact_wallet_loading": "Le portefeuille se charge encore — cochez « Afficher dans chaque portefeuille » ou réessayez dans un instant.",
|
||||||
"contacts": "Contacts",
|
"contacts": "Contacts",
|
||||||
"contacts_search_no_match": "Aucun contact correspondant",
|
"contacts_search_no_match": "Aucun contact correspondant",
|
||||||
"contacts_search_placeholder": "Rechercher des contacts...",
|
"contacts_search_placeholder": "Rechercher des contacts...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "Lignes en vedette",
|
"portfolio_style_featured": "Lignes en vedette",
|
||||||
"portfolio_style_label": "Style du portefeuille",
|
"portfolio_style_label": "Style du portefeuille",
|
||||||
"portfolio_untitled": "Sans titre",
|
"portfolio_untitled": "Sans titre",
|
||||||
|
"portfolio_wallet_loading": "Attendez la fin du chargement du portefeuille pour ajouter un groupe.",
|
||||||
"price_chart": "Graphique des prix",
|
"price_chart": "Graphique des prix",
|
||||||
"privacy_great": "Excellente confidentialité !",
|
"privacy_great": "Excellente confidentialité !",
|
||||||
"privacy_low": "Faible confidentialité — blindez vos fonds",
|
"privacy_low": "Faible confidentialité — blindez vos fonds",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "オン:この連絡先はどのウォレットを読み込んでも表示されます。オフ:現在のウォレットにのみ属します。",
|
"contact_global_tt": "オン:この連絡先はどのウォレットを読み込んでも表示されます。オフ:現在のウォレットにのみ属します。",
|
||||||
"contact_preview_addr": "ここにアドレスが表示されます",
|
"contact_preview_addr": "ここにアドレスが表示されます",
|
||||||
"contact_preview_name": "連絡先名",
|
"contact_preview_name": "連絡先名",
|
||||||
|
"contact_wallet_loading": "ウォレットを読み込み中です。「すべてのウォレットに表示」にチェックするか、少し待ってから再試行してください。",
|
||||||
"contacts": "連絡先",
|
"contacts": "連絡先",
|
||||||
"contacts_search_no_match": "一致する連絡先がありません",
|
"contacts_search_no_match": "一致する連絡先がありません",
|
||||||
"contacts_search_placeholder": "連絡先を検索...",
|
"contacts_search_placeholder": "連絡先を検索...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "注目行",
|
"portfolio_style_featured": "注目行",
|
||||||
"portfolio_style_label": "ポートフォリオスタイル",
|
"portfolio_style_label": "ポートフォリオスタイル",
|
||||||
"portfolio_untitled": "無題",
|
"portfolio_untitled": "無題",
|
||||||
|
"portfolio_wallet_loading": "ウォレットの読み込みが終わってからグループを追加してください。",
|
||||||
"price_chart": "価格チャート",
|
"price_chart": "価格チャート",
|
||||||
"privacy_great": "優れたプライバシーです!",
|
"privacy_great": "優れたプライバシーです!",
|
||||||
"privacy_low": "プライバシーが低い — 資金をシールドしてください",
|
"privacy_low": "プライバシーが低い — 資金をシールドしてください",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "켜짐: 어떤 지갑을 불러오든 이 연락처가 계속 표시됩니다. 꺼짐: 현재 지갑에만 속합니다.",
|
"contact_global_tt": "켜짐: 어떤 지갑을 불러오든 이 연락처가 계속 표시됩니다. 꺼짐: 현재 지갑에만 속합니다.",
|
||||||
"contact_preview_addr": "여기에 주소가 표시됩니다",
|
"contact_preview_addr": "여기에 주소가 표시됩니다",
|
||||||
"contact_preview_name": "연락처 이름",
|
"contact_preview_name": "연락처 이름",
|
||||||
|
"contact_wallet_loading": "지갑을 아직 불러오는 중입니다 — “모든 지갑에 표시”를 선택하거나 잠시 후 다시 시도하세요.",
|
||||||
"contacts": "연락처",
|
"contacts": "연락처",
|
||||||
"contacts_search_no_match": "일치하는 연락처 없음",
|
"contacts_search_no_match": "일치하는 연락처 없음",
|
||||||
"contacts_search_placeholder": "연락처 검색...",
|
"contacts_search_placeholder": "연락처 검색...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "강조 행",
|
"portfolio_style_featured": "강조 행",
|
||||||
"portfolio_style_label": "포트폴리오 스타일",
|
"portfolio_style_label": "포트폴리오 스타일",
|
||||||
"portfolio_untitled": "제목 없음",
|
"portfolio_untitled": "제목 없음",
|
||||||
|
"portfolio_wallet_loading": "지갑 로딩이 끝난 후 그룹을 추가하세요.",
|
||||||
"price_chart": "가격 차트",
|
"price_chart": "가격 차트",
|
||||||
"privacy_great": "프라이버시가 우수합니다!",
|
"privacy_great": "프라이버시가 우수합니다!",
|
||||||
"privacy_low": "낮은 프라이버시 — 자금을 차폐하세요",
|
"privacy_low": "낮은 프라이버시 — 자금을 차폐하세요",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "Ativado: este contato permanece visível em qualquer carteira que você carregar. Desativado: ele pertence apenas à carteira atual.",
|
"contact_global_tt": "Ativado: este contato permanece visível em qualquer carteira que você carregar. Desativado: ele pertence apenas à carteira atual.",
|
||||||
"contact_preview_addr": "O endereço aparecerá aqui",
|
"contact_preview_addr": "O endereço aparecerá aqui",
|
||||||
"contact_preview_name": "Nome do contato",
|
"contact_preview_name": "Nome do contato",
|
||||||
|
"contact_wallet_loading": "A carteira ainda está carregando — marque “Mostrar em todas as carteiras” ou tente novamente em um momento.",
|
||||||
"contacts": "Contatos",
|
"contacts": "Contatos",
|
||||||
"contacts_search_no_match": "Nenhum contato correspondente",
|
"contacts_search_no_match": "Nenhum contato correspondente",
|
||||||
"contacts_search_placeholder": "Pesquisar contatos...",
|
"contacts_search_placeholder": "Pesquisar contatos...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "Linhas em destaque",
|
"portfolio_style_featured": "Linhas em destaque",
|
||||||
"portfolio_style_label": "Estilo do portfólio",
|
"portfolio_style_label": "Estilo do portfólio",
|
||||||
"portfolio_untitled": "Sem título",
|
"portfolio_untitled": "Sem título",
|
||||||
|
"portfolio_wallet_loading": "Aguarde a carteira terminar de carregar para adicionar um grupo.",
|
||||||
"price_chart": "Gráfico de Preços",
|
"price_chart": "Gráfico de Preços",
|
||||||
"privacy_great": "Ótima privacidade!",
|
"privacy_great": "Ótima privacidade!",
|
||||||
"privacy_low": "Baixa privacidade — blinde os fundos",
|
"privacy_low": "Baixa privacidade — blinde os fundos",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "Вкл.: этот контакт остаётся видимым, какой бы кошелёк вы ни загрузили. Выкл.: он принадлежит только текущему кошельку.",
|
"contact_global_tt": "Вкл.: этот контакт остаётся видимым, какой бы кошелёк вы ни загрузили. Выкл.: он принадлежит только текущему кошельку.",
|
||||||
"contact_preview_addr": "Здесь появится адрес",
|
"contact_preview_addr": "Здесь появится адрес",
|
||||||
"contact_preview_name": "Имя контакта",
|
"contact_preview_name": "Имя контакта",
|
||||||
|
"contact_wallet_loading": "Кошелёк ещё загружается — отметьте «Показывать во всех кошельках» или повторите чуть позже.",
|
||||||
"contacts": "Контакты",
|
"contacts": "Контакты",
|
||||||
"contacts_search_no_match": "Совпадающих контактов нет",
|
"contacts_search_no_match": "Совпадающих контактов нет",
|
||||||
"contacts_search_placeholder": "Поиск контактов...",
|
"contacts_search_placeholder": "Поиск контактов...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "Избранные строки",
|
"portfolio_style_featured": "Избранные строки",
|
||||||
"portfolio_style_label": "Стиль портфеля",
|
"portfolio_style_label": "Стиль портфеля",
|
||||||
"portfolio_untitled": "Без названия",
|
"portfolio_untitled": "Без названия",
|
||||||
|
"portfolio_wallet_loading": "Дождитесь загрузки кошелька, чтобы добавить группу.",
|
||||||
"price_chart": "График цен",
|
"price_chart": "График цен",
|
||||||
"privacy_great": "Отличная конфиденциальность!",
|
"privacy_great": "Отличная конфиденциальность!",
|
||||||
"privacy_low": "Низкая конфиденциальность — экранируйте средства",
|
"privacy_low": "Низкая конфиденциальность — экранируйте средства",
|
||||||
|
|||||||
@@ -305,6 +305,7 @@
|
|||||||
"contact_global_tt": "开启:无论您加载哪个钱包,此联系人都保持可见。关闭:它仅属于当前钱包。",
|
"contact_global_tt": "开启:无论您加载哪个钱包,此联系人都保持可见。关闭:它仅属于当前钱包。",
|
||||||
"contact_preview_addr": "地址将显示在此处",
|
"contact_preview_addr": "地址将显示在此处",
|
||||||
"contact_preview_name": "联系人名称",
|
"contact_preview_name": "联系人名称",
|
||||||
|
"contact_wallet_loading": "钱包仍在加载——请选中“在每个钱包中显示”,或稍后再试。",
|
||||||
"contacts": "联系人",
|
"contacts": "联系人",
|
||||||
"contacts_search_no_match": "没有匹配的联系人",
|
"contacts_search_no_match": "没有匹配的联系人",
|
||||||
"contacts_search_placeholder": "搜索联系人...",
|
"contacts_search_placeholder": "搜索联系人...",
|
||||||
@@ -977,6 +978,7 @@
|
|||||||
"portfolio_style_featured": "特色行",
|
"portfolio_style_featured": "特色行",
|
||||||
"portfolio_style_label": "投资组合样式",
|
"portfolio_style_label": "投资组合样式",
|
||||||
"portfolio_untitled": "未命名",
|
"portfolio_untitled": "未命名",
|
||||||
|
"portfolio_wallet_loading": "请等待钱包加载完成后再添加分组。",
|
||||||
"price_chart": "价格图表",
|
"price_chart": "价格图表",
|
||||||
"privacy_great": "隐私性极佳!",
|
"privacy_great": "隐私性极佳!",
|
||||||
"privacy_low": "隐私性低——请屏蔽资金",
|
"privacy_low": "隐私性低——请屏蔽资金",
|
||||||
|
|||||||
@@ -763,10 +763,25 @@ void RenderContactsTab(App* app)
|
|||||||
};
|
};
|
||||||
data::AddressBookEntry entry(trimAB(s_edit_label), trimAB(s_edit_address), s_edit_notes);
|
data::AddressBookEntry entry(trimAB(s_edit_label), trimAB(s_edit_address), s_edit_notes);
|
||||||
entry.avatar = s_edit_avatar;
|
entry.avatar = s_edit_avatar;
|
||||||
// Global if the user asked, or as a safe fallback when we don't yet know the wallet
|
// Scope: global if the user asked; otherwise this wallet — but ONLY when we actually
|
||||||
// (pre-connect) — better a visible-everywhere contact than one orphaned to no wallet.
|
// know which wallet is loaded. While the identity is unknown (the switch / first-load
|
||||||
entry.scope = (s_edit_global || activeHash.empty()) ? std::string("global") : activeHash;
|
// window) don't silently make a wallet-scoped contact global: preserve an edited
|
||||||
if (isEdit) {
|
// contact's existing scope, and refuse a NEW wallet-scoped one (tick global or wait).
|
||||||
|
bool blocked = false;
|
||||||
|
if (s_edit_global) {
|
||||||
|
entry.scope = "global";
|
||||||
|
} else if (!activeHash.empty()) {
|
||||||
|
entry.scope = activeHash;
|
||||||
|
} else if (isEdit && s_selected_index >= 0 && s_selected_index < (int)book.size()) {
|
||||||
|
entry.scope = book.entries()[s_selected_index].scope; // keep; don't demote to global
|
||||||
|
if (entry.scope.empty()) entry.scope = "global";
|
||||||
|
} else {
|
||||||
|
Notifications::instance().error(TR("contact_wallet_loading"));
|
||||||
|
blocked = true; // don't create a wallet-scoped contact with an unknown wallet
|
||||||
|
}
|
||||||
|
if (blocked) {
|
||||||
|
// leave the dialog open so the user can tick global or retry once loaded
|
||||||
|
} else if (isEdit) {
|
||||||
if (app->addressBook().updateEntry(s_selected_index, entry)) {
|
if (app->addressBook().updateEntry(s_selected_index, entry)) {
|
||||||
Notifications::instance().success(TR("address_book_updated"));
|
Notifications::instance().success(TR("address_book_updated"));
|
||||||
s_show_edit_dialog = false;
|
s_show_edit_dialog = false;
|
||||||
@@ -895,9 +910,9 @@ void RenderContactsTab(App* app)
|
|||||||
for (size_t i = 0; i < book.size(); ++i) {
|
for (size_t i = 0; i < book.size(); ++i) {
|
||||||
const auto& e = book.entries()[i];
|
const auto& e = book.entries()[i];
|
||||||
if (!matchesSearch(e, needle)) continue;
|
if (!matchesSearch(e, needle)) continue;
|
||||||
// Scope filter: global contacts + this wallet's contacts. Pre-connect (activeHash empty)
|
// Scope filter: global contacts + this wallet's contacts. When the wallet identity is unknown
|
||||||
// we don't know the wallet yet, so show everything rather than hide contacts.
|
// (switch / first-load window), show only GLOBAL contacts — never another wallet's scoped ones.
|
||||||
if (!activeHash.empty() && !e.visibleInWallet(activeHash)) continue;
|
if (activeHash.empty() ? !e.isGlobal() : !e.visibleInWallet(activeHash)) continue;
|
||||||
visibleRows.push_back(i);
|
visibleRows.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -380,14 +380,14 @@ static bool pfIndexVisible(App* app, int i)
|
|||||||
const auto& es = app->settings()->getPortfolioEntries();
|
const auto& es = app->settings()->getPortfolioEntries();
|
||||||
if (i < 0 || i >= (int)es.size()) return false;
|
if (i < 0 || i >= (int)es.size()) return false;
|
||||||
const std::string h = app->activeWalletIdentityHash();
|
const std::string h = app->activeWalletIdentityHash();
|
||||||
return es[i].scope.empty() || h.empty() || es[i].scope == h;
|
return es[i].scope.empty() || (!h.empty() && es[i].scope == h);
|
||||||
}
|
}
|
||||||
static int pfFirstVisibleIndex(App* app)
|
static int pfFirstVisibleIndex(App* app)
|
||||||
{
|
{
|
||||||
const auto& es = app->settings()->getPortfolioEntries();
|
const auto& es = app->settings()->getPortfolioEntries();
|
||||||
const std::string h = app->activeWalletIdentityHash();
|
const std::string h = app->activeWalletIdentityHash();
|
||||||
for (int i = 0; i < (int)es.size(); i++)
|
for (int i = 0; i < (int)es.size(); i++)
|
||||||
if (es[i].scope.empty() || h.empty() || es[i].scope == h) return i;
|
if (es[i].scope.empty() || (!h.empty() && es[i].scope == h)) return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,7 +823,9 @@ static void RenderPortfolioEditor(App* app)
|
|||||||
const std::string activeHash = app->activeWalletIdentityHash();
|
const std::string activeHash = app->activeWalletIdentityHash();
|
||||||
std::vector<int> vis;
|
std::vector<int> vis;
|
||||||
for (int i = 0; i < (int)entries.size(); i++)
|
for (int i = 0; i < (int)entries.size(); i++)
|
||||||
if (entries[i].scope.empty() || activeHash.empty() || entries[i].scope == activeHash)
|
// Global groups always; this wallet's groups only when the identity is known — never
|
||||||
|
// another wallet's scoped groups during the switch/first-load window.
|
||||||
|
if (entries[i].scope.empty() || (!activeHash.empty() && entries[i].scope == activeHash))
|
||||||
vis.push_back(i);
|
vis.push_back(i);
|
||||||
if (vis.empty())
|
if (vis.empty())
|
||||||
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("portfolio_no_entries"));
|
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("portfolio_no_entries"));
|
||||||
@@ -905,7 +907,11 @@ static void RenderPortfolioEditor(App* app)
|
|||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||||
// Add immediately creates a persisted "Untitled" group and selects it for editing.
|
// Add immediately creates a persisted "Untitled" group scoped to this wallet — so it's disabled
|
||||||
|
// while the wallet identity is unknown (switch / first-load window), otherwise a new group would
|
||||||
|
// get an empty scope and show under every wallet.
|
||||||
|
const bool pfIdentityKnown = !app->activeWalletIdentityHash().empty();
|
||||||
|
ImGui::BeginDisabled(!pfIdentityKnown);
|
||||||
if (material::TactileButton(TR("portfolio_add_entry"), ImVec2(masterW, addH))) {
|
if (material::TactileButton(TR("portfolio_add_entry"), ImVec2(masterW, addH))) {
|
||||||
// Auto-save the current group, then start a fresh one selected for editing.
|
// Auto-save the current group, then start a fresh one selected for editing.
|
||||||
pfCommitIfNeeded(app);
|
pfCommitIfNeeded(app);
|
||||||
@@ -918,6 +924,9 @@ static void RenderPortfolioEditor(App* app)
|
|||||||
s_pfEdit.sel = (int)es.size() - 1;
|
s_pfEdit.sel = (int)es.size() - 1;
|
||||||
PortfolioBeginEdit(app, s_pfEdit.sel);
|
PortfolioBeginEdit(app, s_pfEdit.sel);
|
||||||
}
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
if (!pfIdentityKnown && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
||||||
|
material::Tooltip("%s", TR("portfolio_wallet_loading"));
|
||||||
}
|
}
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|
||||||
@@ -1967,7 +1976,9 @@ static void mktDrawPortfolio(const MktCtx& cx)
|
|||||||
std::vector<int> vis;
|
std::vector<int> vis;
|
||||||
for (int i = 0; i < (int)allEntries.size(); i++) {
|
for (int i = 0; i < (int)allEntries.size(); i++) {
|
||||||
const auto& e = allEntries[i];
|
const auto& e = allEntries[i];
|
||||||
if (e.scope.empty() || activeHash.empty() || e.scope == activeHash) vis.push_back(i);
|
// Global groups always; this wallet's only when the identity is known (never another
|
||||||
|
// wallet's scoped groups during the switch/first-load window).
|
||||||
|
if (e.scope.empty() || (!activeHash.empty() && e.scope == activeHash)) vis.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int style = app->settings() ? app->settings()->getPortfolioStyle() : 0;
|
int style = app->settings() ? app->settings()->getPortfolioStyle() : 0;
|
||||||
@@ -2110,7 +2121,7 @@ void RenderMarketTab(App* app)
|
|||||||
const std::string pfActiveHash = app->activeWalletIdentityHash();
|
const std::string pfActiveHash = app->activeWalletIdentityHash();
|
||||||
int pfVisN = 0;
|
int pfVisN = 0;
|
||||||
for (const auto& e : pfEntriesGeo)
|
for (const auto& e : pfEntriesGeo)
|
||||||
if (e.scope.empty() || pfActiveHash.empty() || e.scope == pfActiveHash) pfVisN++;
|
if (e.scope.empty() || (!pfActiveHash.empty() && e.scope == pfActiveHash)) pfVisN++;
|
||||||
int pfStyle = app->settings()->getPortfolioStyle();
|
int pfStyle = app->settings()->getPortfolioStyle();
|
||||||
float pfRowH = (pfStyle == 0 ? 46.0f : pfStyle == 1 ? 64.0f : 84.0f) * mktDp;
|
float pfRowH = (pfStyle == 0 ? 46.0f : pfStyle == 1 ? 64.0f : 84.0f) * mktDp;
|
||||||
float pfRowGap = Layout::spacingSm();
|
float pfRowGap = Layout::spacingSm();
|
||||||
|
|||||||
@@ -1245,6 +1245,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["contact_avatar_remove"] = "Remove";
|
strings_["contact_avatar_remove"] = "Remove";
|
||||||
strings_["contact_avatar_image_hint"] = "The image is copied into the app so it stays available if the original moves.";
|
strings_["contact_avatar_image_hint"] = "The image is copied into the app so it stays available if the original moves.";
|
||||||
strings_["contact_avatar_copy_failed"] = "Could not copy that image.";
|
strings_["contact_avatar_copy_failed"] = "Could not copy that image.";
|
||||||
|
strings_["contact_wallet_loading"] = "The wallet is still loading — tick \"Show in every wallet\", or try again in a moment.";
|
||||||
strings_["contact_avatar_bad_image"] = "That image couldn't be loaded.";
|
strings_["contact_avatar_bad_image"] = "That image couldn't be loaded.";
|
||||||
strings_["contact_global_badge_tt"] = "Global contact — visible in every wallet";
|
strings_["contact_global_badge_tt"] = "Global contact — visible in every wallet";
|
||||||
strings_["address_book_added"] = "Address added to book";
|
strings_["address_book_added"] = "Address added to book";
|
||||||
@@ -1520,6 +1521,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["portfolio_no_addr_match"] = "No addresses match";
|
strings_["portfolio_no_addr_match"] = "No addresses match";
|
||||||
strings_["portfolio_manage_title"] = "Manage portfolio";
|
strings_["portfolio_manage_title"] = "Manage portfolio";
|
||||||
strings_["portfolio_add_entry"] = "Add entry";
|
strings_["portfolio_add_entry"] = "Add entry";
|
||||||
|
strings_["portfolio_wallet_loading"] = "Wait until the wallet finishes loading to add a group.";
|
||||||
strings_["portfolio_new_entry"] = "New entry";
|
strings_["portfolio_new_entry"] = "New entry";
|
||||||
strings_["portfolio_label"] = "Label";
|
strings_["portfolio_label"] = "Label";
|
||||||
strings_["portfolio_addresses_sel"] = "%d selected";
|
strings_["portfolio_addresses_sel"] = "%d selected";
|
||||||
|
|||||||
Reference in New Issue
Block a user