mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix: hide generated account copy for imported accounts
This commit is contained in:
@@ -7,6 +7,7 @@ import AccountSettings from '../account-settings';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||
const IMPORTED_ACCOUNT_ADDRESSES_STORAGE_KEY = 'importedAccountAddresses';
|
||||
|
||||
const hookMocks = vi.hoisted(() => ({
|
||||
deleteAccount: vi.fn(),
|
||||
@@ -177,6 +178,34 @@ describe('AccountSettings', () => {
|
||||
expect(buttonTexts.some((text) => text.includes('delete_account'))).toBe(true);
|
||||
});
|
||||
|
||||
it('shows generated-account copy for app-created accounts', () => {
|
||||
render();
|
||||
|
||||
const infoText = container.querySelector('select')?.parentElement?.querySelector('div')?.textContent ?? '';
|
||||
expect(infoText).toContain('account_auto_generated');
|
||||
expect(infoText).toContain('stored_locally');
|
||||
});
|
||||
|
||||
it('shows only the stored-locally copy for imported accounts', () => {
|
||||
localStorage.setItem(IMPORTED_ACCOUNT_ADDRESSES_STORAGE_KEY, JSON.stringify(['0x123']));
|
||||
|
||||
render();
|
||||
|
||||
const infoText = container.querySelector('select')?.parentElement?.querySelector('div')?.textContent ?? '';
|
||||
expect(infoText).toContain('stored_locally');
|
||||
expect(infoText).not.toContain('account_auto_generated');
|
||||
});
|
||||
|
||||
it('treats the legacy imported account storage key as imported state', () => {
|
||||
localStorage.setItem('importedAccountAddress', '0x123');
|
||||
|
||||
render();
|
||||
|
||||
const infoText = container.querySelector('select')?.parentElement?.querySelector('div')?.textContent ?? '';
|
||||
expect(infoText).toContain('stored_locally');
|
||||
expect(infoText).not.toContain('account_auto_generated');
|
||||
});
|
||||
|
||||
it('deletes the account only after both confirmations succeed', async () => {
|
||||
confirmSpy.mockReturnValueOnce(true).mockReturnValueOnce(true);
|
||||
|
||||
@@ -314,6 +343,7 @@ describe('AccountSettings', () => {
|
||||
expect(hookMocks.importAccount).toHaveBeenCalledOnce();
|
||||
const importedPayload = JSON.parse(hookMocks.importAccount.mock.calls[0][0]);
|
||||
expect(importedPayload.account.subscriptions).toEqual(['business.eth', 'music-posting.bso']);
|
||||
expect(localStorage.getItem(IMPORTED_ACCOUNT_ADDRESSES_STORAGE_KEY)).toBe(JSON.stringify(['0x999']));
|
||||
expect(localStorage.getItem('importedAccountAddress')).toBe('0x999');
|
||||
expect(hookMocks.setActiveAccount).toHaveBeenCalledWith('Imported');
|
||||
expect(alertSpy).toHaveBeenCalledWith('Imported Imported');
|
||||
|
||||
@@ -6,6 +6,8 @@ import { Capacitor } from '@capacitor/core';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
const isAndroid = Capacitor.getPlatform() === 'android';
|
||||
const IMPORTED_ACCOUNT_ADDRESSES_STORAGE_KEY = 'importedAccountAddresses';
|
||||
const IMPORTED_ACCOUNT_ADDRESS_LEGACY_STORAGE_KEY = 'importedAccountAddress';
|
||||
|
||||
const safeParseJSON = <T,>(value: string): T | null => {
|
||||
try {
|
||||
@@ -24,6 +26,32 @@ const withErrorHandling = async <T,>(fn: () => Promise<T>, onError: (e: unknown)
|
||||
}
|
||||
};
|
||||
|
||||
const readImportedAccountAddresses = (): string[] => {
|
||||
try {
|
||||
const storedAddresses = localStorage.getItem(IMPORTED_ACCOUNT_ADDRESSES_STORAGE_KEY);
|
||||
const parsedAddresses = storedAddresses ? safeParseJSON<unknown>(storedAddresses) : null;
|
||||
const normalizedAddresses = Array.isArray(parsedAddresses)
|
||||
? parsedAddresses.filter((address): address is string => typeof address === 'string' && address.length > 0)
|
||||
: [];
|
||||
const legacyAddress = localStorage.getItem(IMPORTED_ACCOUNT_ADDRESS_LEGACY_STORAGE_KEY);
|
||||
return [...new Set(legacyAddress ? [...normalizedAddresses, legacyAddress] : normalizedAddresses)];
|
||||
} catch (error) {
|
||||
console.warn('Failed to read imported account addresses from localStorage:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const rememberImportedAccountAddress = (address: string) => {
|
||||
try {
|
||||
const importedAddresses = readImportedAccountAddresses();
|
||||
const nextImportedAddresses = [...new Set([...importedAddresses, address])];
|
||||
localStorage.setItem(IMPORTED_ACCOUNT_ADDRESSES_STORAGE_KEY, JSON.stringify(nextImportedAddresses));
|
||||
localStorage.setItem(IMPORTED_ACCOUNT_ADDRESS_LEGACY_STORAGE_KEY, address);
|
||||
} catch (error) {
|
||||
console.warn('Failed to save imported account address to localStorage:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Inner component keyed by account id so state resets when user switches account
|
||||
const AccountSettingsEditor = ({
|
||||
account,
|
||||
@@ -125,7 +153,7 @@ const AccountSettingsEditor = ({
|
||||
async () => {
|
||||
await importAccount(modifiedAccountJson);
|
||||
if (accountData.account?.author?.address) {
|
||||
localStorage.setItem('importedAccountAddress', accountData.account.author.address);
|
||||
rememberImportedAccountAddress(accountData.account.author.address);
|
||||
}
|
||||
if (accountData.account?.name) {
|
||||
await setActiveAccount(accountData.account.name);
|
||||
@@ -163,6 +191,10 @@ const AccountSettingsEditor = ({
|
||||
));
|
||||
|
||||
const host = window.electronApi?.isElectron ? 'this desktop app' : isAndroid ? 'this mobile app' : window.location.hostname;
|
||||
const isImportedAccount = typeof account?.author?.address === 'string' && readImportedAccountAddresses().includes(account.author.address);
|
||||
const accountStorageInfo = isImportedAccount
|
||||
? t('stored_locally', { location: host, interpolation: { escapeValue: false } })
|
||||
: `${t('account_auto_generated')} ${t('stored_locally', { location: host, interpolation: { escapeValue: false } })}`;
|
||||
|
||||
return (
|
||||
<div className={styles.setting}>
|
||||
@@ -172,9 +204,7 @@ const AccountSettingsEditor = ({
|
||||
</select>{' '}
|
||||
<button onClick={() => navigate('/settings/account-data', { state: { returnTo: location.pathname + location.hash } })}>{t('edit')}</button>{' '}
|
||||
<button onClick={handleExportAccount}>{t('download_backup')}</button>
|
||||
<div className={styles.info}>
|
||||
{t('account_auto_generated')} {t('stored_locally', { location: host, interpolation: { escapeValue: false } })}
|
||||
</div>
|
||||
<div className={styles.info}>{accountStorageInfo}</div>
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={handleImportAccount}>{t('import_account_backup')}</button>
|
||||
|
||||
Reference in New Issue
Block a user