Skip to content

Commit

Permalink
refactor: Update useAccountStore.js to refresh and set accounts
Browse files Browse the repository at this point in the history
The code changes in `useAccountStore.js` add the `refreshAccounts` and `setAccounts` functions. The `refreshAccounts` function retrieves the active accounts from the database and updates the `accounts` state. The `setAccounts` function allows setting the `accounts` state directly. These changes improve the functionality of the account store.

This commit message follows the established convention of starting with a verb in the imperative form ("Update") and providing a concise summary of the changes made.
  • Loading branch information
IZUMI-Zu committed Aug 29, 2024
1 parent 18ec196 commit ee2d311
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 99 deletions.
195 changes: 97 additions & 98 deletions HomePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,15 @@ import {useNetInfo} from "@react-native-community/netinfo";
import {CountdownCircleTimer} from "react-native-countdown-circle-timer";
import {FlashList} from "@shopify/flash-list";
import Toast from "react-native-toast-message";
import {useLiveQuery} from "drizzle-orm/expo-sqlite";
import {isNull} from "drizzle-orm";

import SearchBar from "./SearchBar";
import EnterAccountDetails from "./EnterAccountDetails";
import ScanQRCode from "./ScanQRCode";
import EditAccountDetails from "./EditAccountDetails";
import AvatarWithFallback from "./AvatarWithFallback";
import useStore from "./useStorage";
import * as schema from "./db/schema";
import {db} from "./db/client";
import {calculateCountdown, generateToken, validateSecret} from "./totpUtil";
import {useAccountSync, useEditAccount, useUpdateAccountToken} from "./useAccountStore";
import {useAccountStore, useAccountSync, useEditAccount, useUpdateAccountToken} from "./useAccountStore";

const {width, height} = Dimensions.get("window");
const REFRESH_INTERVAL = 10000;
Expand All @@ -44,7 +40,6 @@ export default function HomePage() {
const [showOptions, setShowOptions] = useState(false);
const [showEnterAccountModal, setShowEnterAccountModal] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const {data: accounts} = useLiveQuery(db.select().from(schema.accounts).where(isNull(schema.accounts.deletedAt)));
const [filteredData, setFilteredData] = useState(accounts);
const [showScanner, setShowScanner] = useState(false);
const [showEditAccountModal, setShowEditAccountModal] = useState(false);
Expand All @@ -57,8 +52,14 @@ export default function HomePage() {
const swipeableRef = useRef(null);
const {userInfo, serverUrl, token} = useStore();
const {startSync} = useAccountSync();
const {updateToken, updateAllTokens} = useUpdateAccountToken();
const {accounts, refreshAccounts} = useAccountStore();
// const {updateToken, updateAllTokens} = useUpdateAccountToken();
const {setAccount, updateAccount, insertAccount, insertAccounts, deleteAccount} = useEditAccount();
const [key, setKey] = useState(0);

useEffect(() => {
refreshAccounts();
}, []);

useEffect(() => {
setCanSync(Boolean(isConnected && userInfo && serverUrl));
Expand All @@ -70,7 +71,10 @@ export default function HomePage() {

useEffect(() => {
const timer = setInterval(() => {
if (canSync) {startSync(userInfo, serverUrl, token);}
if (canSync) {
startSync(userInfo, serverUrl, token);
refreshAccounts();
}
}, REFRESH_INTERVAL);
return () => clearInterval(timer);
}, [startSync]);
Expand All @@ -95,6 +99,7 @@ export default function HomePage() {
});
}
}
refreshAccounts();
setRefreshing(false);
};

Expand All @@ -106,6 +111,7 @@ export default function HomePage() {
await insertAccount();
closeEnterAccountModal();
}
refreshAccounts();
};

const handleEditAccount = (account) => {
Expand All @@ -119,12 +125,18 @@ export default function HomePage() {
if (editingAccount) {
setAccount({...editingAccount, accountName: newAccountName, oldAccountName: editingAccount.accountName});
updateAccount();
refreshAccounts();
setPlaceholder("");
setEditingAccount(null);
closeEditAccountModal();
}
};

const onAccountDelete = async(account) => {
deleteAccount(account.id);
refreshAccounts();
};

const closeEditAccountModal = () => setShowEditAccountModal(false);

const handleScanPress = () => {
Expand Down Expand Up @@ -177,107 +189,94 @@ export default function HomePage() {
);
};

const SwipeableItem = ({item, handleEditAccount, deleteAccount, generateToken, calculateCountdown}) => {
const [token, setToken] = useState(() => generateToken(item.secretKey));
const swipeableRef = useRef(null);

const renderRightActions = () => (
<View style={{flexDirection: "row", alignItems: "center"}}>
<TouchableOpacity
style={{height: 70, width: 80, backgroundColor: "#E6DFF3", alignItems: "center", justifyContent: "center"}}
onPress={() => handleEditAccount(item)}
>
<Text>Edit</Text>
</TouchableOpacity>
<TouchableOpacity
style={{height: 70, width: 80, backgroundColor: "#FFC0CB", alignItems: "center", justifyContent: "center"}}
onPress={() => deleteAccount(item.id)}
>
<Text>Delete</Text>
</TouchableOpacity>
</View>
);

return (
<GestureHandlerRootView>
<Swipeable
ref={swipeableRef}
renderRightActions={renderRightActions}
>
<List.Item
style={{
height: 80,
paddingHorizontal: 25,
justifyContent: "center",
}}
title={
<View style={{justifyContent: "center", paddingLeft: 0, paddingTop: 6}}>
<Text variant="titleMedium" numberOfLines={1}>
{item.accountName}
</Text>
<Text variant="titleLarge" style={{fontWeight: "bold"}}>{token}</Text>
</View>
}
left={() => (
<AvatarWithFallback
source={{uri: item.issuer ? `https://cdn.casbin.org/img/social_${item.issuer.toLowerCase()}.png` : "https://cdn.casbin.org/img/social_default.png"}}
fallbackSource={{uri: "https://cdn.casbin.org/img/social_default.png"}}
size={60}
style={{
borderRadius: 10,
backgroundColor: "transparent",
}}
/>
)}
right={() => (
<View style={{justifyContent: "center", alignItems: "center"}}>
<CountdownCircleTimer
isPlaying={true}
duration={30}
initialRemainingTime={calculateCountdown()}
colors={["#004777", "#0072A0", "#0099CC", "#FF6600", "#CC3300", "#A30000"]}
colorsTime={[30, 24, 18, 12, 6, 0]}
size={60}
onComplete={() => {
setToken(generateToken(item.secretKey));
return {
shouldRepeat: true,
delay: 0,
newInitialRemainingTime: calculateCountdown(),
};
}}
strokeWidth={5}
>
{({remainingTime}) => (
<Text style={{fontSize: 18, fontWeight: "bold"}}>{remainingTime}s</Text>
)}
</CountdownCircleTimer>
</View>
)}
/>
</Swipeable>
</GestureHandlerRootView>
);
};

return (
<View style={{flex: 1}}>
<SearchBar onSearch={handleSearch} />
<FlashList
data={searchQuery.trim() !== "" ? filteredData : accounts}
extraData={key}
keyExtractor={(item) => `${item.id}`}
estimatedItemSize={80}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
renderItem={({item}) =>
<SwipeableItem
item={item}
handleEditAccount={handleEditAccount}
deleteAccount={deleteAccount}
generateToken={generateToken}
calculateCountdown={calculateCountdown}
/>}
<GestureHandlerRootView>
<Swipeable
ref={swipeableRef}
renderRightActions={() => {
return (
<View style={{flexDirection: "row", alignItems: "center"}}>
<TouchableOpacity
style={{height: 70, width: 80, backgroundColor: "#E6DFF3", alignItems: "center", justifyContent: "center"}}
onPress={() => handleEditAccount(item)}
>
<Text>Edit</Text>
</TouchableOpacity>
<TouchableOpacity
style={{height: 70, width: 80, backgroundColor: "#FFC0CB", alignItems: "center", justifyContent: "center"}}
onPress={() => onAccountDelete(item)}
>
<Text>Delete</Text>
</TouchableOpacity>
</View>
);
}
}
>
<List.Item
style={{
height: 80,
paddingHorizontal: 25,
justifyContent: "center",
}}
title={
<View style={{justifyContent: "center", paddingLeft: 0, paddingTop: 6}}>
<Text variant="titleMedium" numberOfLines={1}>
{item.accountName}
</Text>
<Text variant="titleLarge" style={{fontWeight: "bold"}}>{generateToken(item.secretKey)}</Text>
</View>
}
left={() => (
<AvatarWithFallback
source={{uri: `https://cdn.casbin.org/img/social_${item.issuer?.toLowerCase()}.png`}}
fallbackSource={{uri: "https://cdn.casbin.org/img/social_default.png"}}
size={60}
style={{
borderRadius: 10,
backgroundColor: "transparent",
}}
/>
)}
right={() => (
<View style={{justifyContent: "center", alignItems: "center"}}>
<CountdownCircleTimer
isPlaying={true}
duration={30}
initialRemainingTime={calculateCountdown()}
colors={["#004777", "#0072A0", "#0099CC", "#FF6600", "#CC3300", "#A30000"]}
colorsTime={[30, 24, 18, 12, 6, 0]}
size={60}
onComplete={() => {
setKey(prevKey => prevKey + 1);
return {
shouldRepeat: true,
delay: 0,
newInitialRemainingTime: calculateCountdown(),
};
}}
strokeWidth={5}
>
{({remainingTime}) => (
<Text style={{fontSize: 18, fontWeight: "bold"}}>{remainingTime}s</Text>
)}
</CountdownCircleTimer>
</View>
)}
/>
</Swipeable>
</GestureHandlerRootView>}
ItemSeparatorComponent={() => <Divider />}
/>

Expand Down
12 changes: 11 additions & 1 deletion useAccountStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ import {create} from "zustand";
import {generateToken} from "./totpUtil";
import {syncWithCloud} from "./syncLogic";

export const useAccountStore = create((set, get) => ({
accounts: [],
refreshAccounts: () => {
const accounts = db.select().from(schema.accounts).where(isNull(schema.accounts.deletedAt)).all();
set({accounts});
},
setAccounts: (accounts) => {
set({accounts});
},
}));

const useEditAccountStore = create((set, get) => ({
account: {id: undefined, issuer: undefined, accountName: undefined, secretKey: undefined, oldAccountName: undefined},
setAccount: (account) => {
Expand Down Expand Up @@ -78,7 +89,6 @@ const useEditAccountStore = create((set, get) => ({
set({account: {id: undefined, issuer: undefined, accountName: undefined, secretKey: undefined}});
},
insertAccounts: (accounts) => {
console.log(accounts);
db.transaction(async(tx) => {
for (const account of accounts) {
const {accountName, issuer, secretKey} = account;
Expand Down

0 comments on commit ee2d311

Please sign in to comment.