import { Dispatch } from 'redux';
import { localStorageKeys } from 'src/constants/localStorageKeys';

import {
  Account,
  AccountValue,
  Accounts,
  DefaultAccount,
} from 'src/types/defaultAccount';
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { POCKET } from '../../utils/config';
import { RootState } from '../store';

type SliceState = {
  actionBar: {
    tweet: string;
  };
  defaultAccount: DefaultAccount;
  accounts: null | Accounts;
};

const initialState: SliceState = {
  actionBar: {
    tweet: POCKET.STAGE_TWEET_ACTION_BAR.TWEET, // stage for tweet ActionBar: 'addAvatar' 'follow' 'tweet'
  },
  defaultAccount: {
    name: null,
    account: null,
  },
  accounts: null,
};

const checkAddress = (obj, network, address) =>
  Object.keys(obj).some((k) => {
    if (obj[k][network]) {
      return obj[k][network].bech32 === address;
    }
  });

function saveToLocalStorage(state: SliceState) {
  const { defaultAccount, accounts } = state;

  defaultAccount &&
    localStorage.setItem(
      localStorageKeys.pocket.POCKET,
      JSON.stringify({
        [defaultAccount.name]: defaultAccount.account,
      })
    );
  accounts &&
    localStorage.setItem(
      localStorageKeys.pocket.POCKET_ACCOUNT,
      JSON.stringify(accounts)
    );
}

const slice = createSlice({
  name: 'pocket',
  initialState,
  reducers: {
    setDefaultAccount: (
      state,
      {
        payload: { name, account },
      }: PayloadAction<{ name: string; account?: Account }>
    ) => {
      state.defaultAccount = {
        name,
        account: account || state.accounts?.[name] || null,
      };

      saveToLocalStorage(state);
    },
    setAccounts: (state, { payload }: PayloadAction<Accounts>) => {
      state.accounts = payload;

      saveToLocalStorage(state);
    },
    setStageTweetActionBar: (state, { payload }: PayloadAction<string>) => {
      state.actionBar.tweet = payload;
    },

    // bullshit
    deleteAddress: (state, { payload }: PayloadAction<string>) => {
      if (state.accounts) {
        Object.keys(state.accounts).forEach((accountKey) => {
          Object.keys(state.accounts[accountKey]).forEach((networkKey) => {
            if (state.accounts[accountKey][networkKey].bech32 === payload) {
              delete state.accounts[accountKey][networkKey];

              if (Object.keys(state.accounts[accountKey]).length === 0) {
                delete state.accounts[accountKey];
              }

              if (state.defaultAccount?.account?.cyber?.bech32 === payload) {
                const entries = Object.entries(state.accounts);

                const entryCyber = entries.find(
                  ([, value]) => value.cyber?.bech32
                );

                if (entryCyber) {
                  state.defaultAccount = {
                    name: entryCyber[0],
                    account: entryCyber[1],
                  };
                } else {
                  state.defaultAccount = {
                    name: null,
                    account: null,
                  };
                }
              }

              saveToLocalStorage(state);
            }
          });
        });
      }
    },
  },
});

export const selectCurrentAddress = (store: RootState) =>
  store.pocket.defaultAccount.account?.cyber?.bech32;

export const {
  setDefaultAccount,
  setAccounts,
  setStageTweetActionBar,
  deleteAddress,
} = slice.actions;

export default slice.reducer;

// refactor this
export const initPocket = () => (dispatch: Dispatch) => {
  let defaultAccounts = null;
  let defaultAccountsKeys = null;
  let accountsTemp: Accounts | null = null;

  const localStoragePocketAccount = localStorage.getItem(
    localStorageKeys.pocket.POCKET_ACCOUNT
  );
  const localStoragePocket = localStorage.getItem(
    localStorageKeys.pocket.POCKET
  );
  if (localStoragePocket !== null) {
    const localStoragePocketData = JSON.parse(localStoragePocket);
    const keyPocket = Object.keys(localStoragePocketData)[0];
    const accountPocket = Object.values(localStoragePocketData)[0];
    defaultAccounts = accountPocket;
    defaultAccountsKeys = keyPocket;
  }
  if (localStoragePocketAccount !== null) {
    const localStoragePocketAccountData = JSON.parse(localStoragePocketAccount);
    if (localStoragePocket === null) {
      const keys0 = Object.keys(localStoragePocketAccountData)[0];
      localStorage.setItem(
        localStorageKeys.pocket.POCKET,
        JSON.stringify({ [keys0]: localStoragePocketAccountData[keys0] })
      );
      defaultAccounts = localStoragePocketAccountData[keys0];
      defaultAccountsKeys = keys0;
    } else if (defaultAccountsKeys !== null) {
      accountsTemp = {
        [defaultAccountsKeys]:
          localStoragePocketAccountData[defaultAccountsKeys] || undefined,
        ...localStoragePocketAccountData,
      };
    }
  } else {
    localStorage.removeItem(localStorageKeys.pocket.POCKET);
    localStorage.removeItem(localStorageKeys.pocket.POCKET_ACCOUNT);
  }

  defaultAccountsKeys &&
    defaultAccounts &&
    dispatch(
      setDefaultAccount({
        name: defaultAccountsKeys,
        account: defaultAccounts,
      })
    );

  accountsTemp &&
    Object.keys(accountsTemp).forEach((key) => {
      if (!accountsTemp[key] || Object.keys(accountsTemp[key]).length === 0) {
        delete accountsTemp[key];
      }
    });

  accountsTemp && dispatch(setAccounts(accountsTemp));
};

const defaultNameAccount = () => {
  let key = 'Account 1';
  let count = 1;

  const localStorageCount = localStorage.getItem('count');

  if (localStorageCount !== null) {
    const dataCount = JSON.parse(localStorageCount);
    count = parseFloat(dataCount);
    key = `Account ${count}`;
  }

  localStorage.setItem('count', JSON.stringify(count + 1));

  return key;
};

export const addAddressPocket =
  (accounts: AccountValue) => (dispatch: Dispatch) => {
    const key = accounts.name || defaultNameAccount();

    let dataPocketAccount = null;
    let valueObj = {};
    let pocketAccount: Accounts = {};

    const localStorageStory = localStorage.getItem(
      localStorageKeys.pocket.POCKET_ACCOUNT
    );

    if (localStorageStory !== null) {
      dataPocketAccount = JSON.parse(localStorageStory);
      valueObj = Object.values(dataPocketAccount);
    }

    const isAdded = !checkAddress(valueObj, 'cyber', accounts.bech32);

    if (!isAdded) {
      return;
    }

    const cyberAccounts: Account = {
      cyber: accounts,
    };

    if (localStorageStory !== null) {
      pocketAccount = { [key]: cyberAccounts, ...dataPocketAccount };
    } else {
      pocketAccount = { [key]: cyberAccounts };
    }

    if (Object.keys(pocketAccount).length > 0) {
      dispatch(setAccounts(pocketAccount));
      if (accounts.keys !== 'read-only') {
        dispatch(setDefaultAccount({ name: key, account: cyberAccounts }));
      }
    }
  };

Synonyms

cyb/src/redux/features/pocket.ts

Neighbours