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:
2026-07-15 12:45:18 -05:00
parent fc509a9340
commit 122db9d903
11 changed files with 57 additions and 13 deletions

View File

@@ -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_preview_addr": "Adresse erscheint hier",
"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_search_no_match": "Keine passenden Kontakte",
"contacts_search_placeholder": "Kontakte durchsuchen...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "Hervorgehobene Zeilen",
"portfolio_style_label": "Portfolio-Stil",
"portfolio_untitled": "Ohne Titel",
"portfolio_wallet_loading": "Warte, bis die Wallet fertig geladen ist, um eine Gruppe hinzuzufügen.",
"price_chart": "Preisdiagramm",
"privacy_great": "Großartige Privatsphäre!",
"privacy_low": "Geringe Privatsphäre — Gelder abschirmen",

View File

@@ -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_preview_addr": "La dirección aparecerá aquí",
"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_search_no_match": "No hay contactos coincidentes",
"contacts_search_placeholder": "Buscar contactos...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "Filas destacadas",
"portfolio_style_label": "Estilo de cartera",
"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",
"privacy_great": "¡Excelente privacidad!",
"privacy_low": "Privacidad baja: protege los fondos",

View File

@@ -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_preview_addr": "L'adresse apparaîtra ici",
"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_search_no_match": "Aucun contact correspondant",
"contacts_search_placeholder": "Rechercher des contacts...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "Lignes en vedette",
"portfolio_style_label": "Style du portefeuille",
"portfolio_untitled": "Sans titre",
"portfolio_wallet_loading": "Attendez la fin du chargement du portefeuille pour ajouter un groupe.",
"price_chart": "Graphique des prix",
"privacy_great": "Excellente confidentialité !",
"privacy_low": "Faible confidentialité — blindez vos fonds",

View File

@@ -305,6 +305,7 @@
"contact_global_tt": "オン:この連絡先はどのウォレットを読み込んでも表示されます。オフ:現在のウォレットにのみ属します。",
"contact_preview_addr": "ここにアドレスが表示されます",
"contact_preview_name": "連絡先名",
"contact_wallet_loading": "ウォレットを読み込み中です。「すべてのウォレットに表示」にチェックするか、少し待ってから再試行してください。",
"contacts": "連絡先",
"contacts_search_no_match": "一致する連絡先がありません",
"contacts_search_placeholder": "連絡先を検索...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "注目行",
"portfolio_style_label": "ポートフォリオスタイル",
"portfolio_untitled": "無題",
"portfolio_wallet_loading": "ウォレットの読み込みが終わってからグループを追加してください。",
"price_chart": "価格チャート",
"privacy_great": "優れたプライバシーです!",
"privacy_low": "プライバシーが低い — 資金をシールドしてください",

View File

@@ -305,6 +305,7 @@
"contact_global_tt": "켜짐: 어떤 지갑을 불러오든 이 연락처가 계속 표시됩니다. 꺼짐: 현재 지갑에만 속합니다.",
"contact_preview_addr": "여기에 주소가 표시됩니다",
"contact_preview_name": "연락처 이름",
"contact_wallet_loading": "지갑을 아직 불러오는 중입니다 — “모든 지갑에 표시”를 선택하거나 잠시 후 다시 시도하세요.",
"contacts": "연락처",
"contacts_search_no_match": "일치하는 연락처 없음",
"contacts_search_placeholder": "연락처 검색...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "강조 행",
"portfolio_style_label": "포트폴리오 스타일",
"portfolio_untitled": "제목 없음",
"portfolio_wallet_loading": "지갑 로딩이 끝난 후 그룹을 추가하세요.",
"price_chart": "가격 차트",
"privacy_great": "프라이버시가 우수합니다!",
"privacy_low": "낮은 프라이버시 — 자금을 차폐하세요",

View File

@@ -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_preview_addr": "O endereço aparecerá aqui",
"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_search_no_match": "Nenhum contato correspondente",
"contacts_search_placeholder": "Pesquisar contatos...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "Linhas em destaque",
"portfolio_style_label": "Estilo do portfólio",
"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",
"privacy_great": "Ótima privacidade!",
"privacy_low": "Baixa privacidade — blinde os fundos",

View File

@@ -305,6 +305,7 @@
"contact_global_tt": "Вкл.: этот контакт остаётся видимым, какой бы кошелёк вы ни загрузили. Выкл.: он принадлежит только текущему кошельку.",
"contact_preview_addr": "Здесь появится адрес",
"contact_preview_name": "Имя контакта",
"contact_wallet_loading": "Кошелёк ещё загружается — отметьте «Показывать во всех кошельках» или повторите чуть позже.",
"contacts": "Контакты",
"contacts_search_no_match": "Совпадающих контактов нет",
"contacts_search_placeholder": "Поиск контактов...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "Избранные строки",
"portfolio_style_label": "Стиль портфеля",
"portfolio_untitled": "Без названия",
"portfolio_wallet_loading": "Дождитесь загрузки кошелька, чтобы добавить группу.",
"price_chart": "График цен",
"privacy_great": "Отличная конфиденциальность!",
"privacy_low": "Низкая конфиденциальность — экранируйте средства",

View File

@@ -305,6 +305,7 @@
"contact_global_tt": "开启:无论您加载哪个钱包,此联系人都保持可见。关闭:它仅属于当前钱包。",
"contact_preview_addr": "地址将显示在此处",
"contact_preview_name": "联系人名称",
"contact_wallet_loading": "钱包仍在加载——请选中“在每个钱包中显示”,或稍后再试。",
"contacts": "联系人",
"contacts_search_no_match": "没有匹配的联系人",
"contacts_search_placeholder": "搜索联系人...",
@@ -977,6 +978,7 @@
"portfolio_style_featured": "特色行",
"portfolio_style_label": "投资组合样式",
"portfolio_untitled": "未命名",
"portfolio_wallet_loading": "请等待钱包加载完成后再添加分组。",
"price_chart": "价格图表",
"privacy_great": "隐私性极佳!",
"privacy_low": "隐私性低——请屏蔽资金",