Skip to content

Commit

Permalink
Fix bugs and add new features
Browse files Browse the repository at this point in the history
  • Loading branch information
Jun-Murakami committed May 5, 2024
1 parent 4f24f6c commit c4d4f5c
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 64 deletions.
26 changes: 18 additions & 8 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ exports.addUserToTree = functions.https.onCall(async (data: { email: string; tre
}
});

// trees/$treeId/timestampに現在の時間を追加
const timestampRef = admin.database().ref(`trees/${treeId}/timestamp`);
await timestampRef.set(Date.now());

return { success: true };
} catch (error) {
console.error('Error adding user to tree:', error);
Expand Down Expand Up @@ -185,10 +181,6 @@ exports.removeUserFromTree = functions.https.onCall(async (data: { treeId: strin
}
});

// trees/$treeId/timestampに現在の時間を追加
const timestampRef = admin.database().ref(`trees/${treeId}/timestamp`);
await timestampRef.set(Date.now());

return { success: true };
} catch (error) {
console.error('Error removing user from tree:', error);
Expand Down Expand Up @@ -280,6 +272,7 @@ exports.updateTimestamps = functions.https.onCall(async (data: { uids: string[],
await Promise.all(
uids.map(async (uid) => {
const userRef = db.ref(`users/${uid}`);
await userRef.update({ timestampV2: timestamp });
await userRef.update({ timestamp: timestamp });
})
);
Expand All @@ -288,4 +281,21 @@ exports.updateTimestamps = functions.https.onCall(async (data: { uids: string[],
console.error('Error updating timestamps:', error);
throw new functions.https.HttpsError('unknown', 'Failed to update timestamps');
}
});

// 指定されたツリーのタイムスタンプを更新
exports.updateTreeTimestamp = functions.https.onCall(async (data: { treeId: string, timestamp: number }) => {
const { treeId, timestamp } = data;
if (!treeId || !timestamp) {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with valid "treeId" and "timestamp".');
}
try {
const db = admin.database();
const treeRef = db.ref(`trees/${treeId}`);
await treeRef.update({ timestamp: timestamp });
return { success: true };
} catch (error) {
console.error('Error updating tree timestamp:', error);
throw new functions.https.HttpsError('unknown', 'Failed to update tree timestamp');
}
});
17 changes: 17 additions & 0 deletions src/components/QuickMemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import DriveFileRenameOutlineIcon from '@mui/icons-material/DriveFileRenameOutline';
import SaveAsIcon from '@mui/icons-material/SaveAs';
import ClearIcon from '@mui/icons-material/Clear';
import { useAppStateStore } from '../store/appStateStore';

export const QuickMemo = () => {
Expand All @@ -34,6 +35,7 @@ export const QuickMemo = () => {
useEffect(() => {
const handleResize = () => {
setWindowHeight(window.innerHeight);
console.log(windowHeight);
if (windowHeight < 600 || isMobile) {
setTextFieldRows(6);
} else {
Expand All @@ -46,6 +48,7 @@ export const QuickMemo = () => {

// コンポーネントのアンマウント時にイベントリスナーを削除
return () => window.removeEventListener('resize', handleResize);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
Expand Down Expand Up @@ -167,6 +170,20 @@ export const QuickMemo = () => {
<SaveAsIcon />
</IconButton>
)}
{isQuickMemoExpanded && quickMemoText && quickMemoText !== '' && (
<IconButton
sx={{
position: 'absolute',
color: theme.palette.grey[500],
bottom:
windowHeight < 600 ? 'calc(env(safe-area-inset-bottom) + 150x)' : 'calc(env(safe-area-inset-bottom) + 318px)',
right: 15,
}}
onClick={() => setQuickMemoText('')}
>
<ClearIcon />
</IconButton>
)}
</AccordionDetails>
</Accordion>
</Box>
Expand Down
5 changes: 1 addition & 4 deletions src/components/SortableTree/MenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,6 @@ export function MenuItemsAttachedFile({ attachedFile }: MenuItemsAttachedFilePro

const anchorElParent = useRef<HTMLButtonElement>(null);
const prevAttachedFileRef = useRef<string | null>(null);
const currentTreeRef = useRef<UniqueIdentifier | null>(null);

const theme = useTheme();

Expand All @@ -508,7 +507,7 @@ export function MenuItemsAttachedFile({ attachedFile }: MenuItemsAttachedFilePro
};

useEffect(() => {
if (prevAttachedFileRef.current !== attachedFile || currentTreeRef.current !== currentTree) {
if (prevAttachedFileRef.current !== attachedFile) {
if (attachedFile?.match(/\.(jpg|jpeg|png|gif|svg|webp|tif|tiff|bmp|ico|cur)$/i) && currentTree) {
const storage = getStorage();
const imageRef = ref(storage, `trees/${currentTree}/${attachedFile}`);
Expand All @@ -525,8 +524,6 @@ export function MenuItemsAttachedFile({ attachedFile }: MenuItemsAttachedFilePro
}
// 現在のattachedFileを記録
prevAttachedFileRef.current = attachedFile;
// 現在のcurrentTreeを記録
currentTreeRef.current = currentTree;
}, [attachedFile, currentTree]);

return (
Expand Down
6 changes: 4 additions & 2 deletions src/hooks/useAppStateManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const useAppStateManagement = () => {
const setDarkMode = useAppStateStore((state) => state.setDarkMode);
const setHideDoneItems = useAppStateStore((state) => state.setHideDoneItems);
const setQuickMemoText = useAppStateStore((state) => state.setQuickMemoText);
const setIsLoadedMemoFromDb = useAppStateStore((state) => state.setIsLoadedMemoFromDb);

const { saveTimeStampDb } = useDatabase();
// エラーハンドリング
Expand Down Expand Up @@ -53,6 +54,7 @@ export const useAppStateManagement = () => {
const data = snapshot.val();
if (typeof data === 'string') {
// クイックメモの内容をセット
setIsLoadedMemoFromDb(true);
setQuickMemoText(data);
}
}
Expand All @@ -70,8 +72,8 @@ export const useAppStateManagement = () => {
}
try {
const userSettingsRef = ref(db, `users/${uid}/settings`);
await saveTimeStampDb();
await set(userSettingsRef, { darkMode: darkModeNew, hideDoneItems: hideDoneItemsNew });
await saveTimeStampDb(null);
} catch (error) {
handleError(error);
}
Expand All @@ -84,8 +86,8 @@ export const useAppStateManagement = () => {
}
try {
const quickMemoRef = ref(getDatabase(), `users/${uid}/quickMemo`);
await saveTimeStampDb();
await set(quickMemoRef, quickMemoText);
await saveTimeStampDb(null);
} catch (error) {
handleError('クイックメモの変更をデータベースに保存できませんでした。\n\n' + error);
}
Expand Down
45 changes: 28 additions & 17 deletions src/hooks/useDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ import { useError } from './useError';

export const useDatabase = () => {
const uid = useAppStateStore((state) => state.uid);
const currentTree = useTreeStateStore((state) => state.currentTree);
const currentTreeMembers = useTreeStateStore((state) => state.currentTreeMembers);
const setLocalTimestamp = useAppStateStore((state) => state.setLocalTimestamp);
const showDialog = useDialogStore((state) => state.showDialog);

const { handleError } = useError();

// タイムスタンプをデータベースに保存する関数 ---------------------------------------------------------------------------
const saveTimeStampDb = async () => {
const saveTimeStampDb = async (targetTree: UniqueIdentifier | null) => {
if (!uid) {
return;
}
Expand All @@ -35,25 +34,29 @@ export const useDatabase = () => {
// indexDBのタイムスタンプを更新
await idb.appstate.update(1, { timestamp: newTimestamp });

// ユーザーのタイムスタンプを更新
const timestampRef = ref(getDatabase(), `users/${uid}/timestamp`);
await set(timestampRef, newTimestamp);

// ユーザーのタイムスタンプV2を更新
const timestampV2Ref = ref(getDatabase(), `users/${uid}/timestampV2`);
await set(timestampV2Ref, newTimestamp);

// ユーザーのタイムスタンプを更新
const timestampRef = ref(getDatabase(), `users/${uid}/timestamp`);
await set(timestampRef, newTimestamp);

// ツリーのタイムスタンプを更新
if (currentTree) {
const treeRef = ref(getDatabase(), `trees/${currentTree}/timestamp`);
await set(treeRef, newTimestamp);
if (targetTree) {
const treeRef = ref(getDatabase(), `trees/${targetTree}/timestamp`);
await set(treeRef, newTimestamp).catch(async (error) => {
if (error.code === 'PERMISSION_DENIED') {
const updateTreeTimestamp = httpsCallable(getFunctions(), 'updateTreeTimestamp');
await updateTreeTimestamp({ treeId: targetTree, timestamp: newTimestamp });
}
});
}

// 自分以外のメンバーのuidを抽出してタイムスタンプを更新
const treeMemberUids = currentTreeMembers?.filter((member) => member.uid !== uid).map((member) => member.uid);
if (treeMemberUids && treeMemberUids.length > 0) {
const functions = getFunctions();
const updateTimestamps = httpsCallable(functions, 'updateTimestamps');
const updateTimestamps = httpsCallable(getFunctions(), 'updateTimestamps');
await updateTimestamps({ uids: treeMemberUids, timestamp: newTimestamp });
}

Expand Down Expand Up @@ -111,10 +114,10 @@ export const useDatabase = () => {
.then(async (snapshot) => {
if (snapshot.exists()) {
// 存在する場合、更新を実行
await saveTimeStampDb();
await set(treeStateRef, newItems).catch((error) => {
handleError('データベースの保存に失敗しました。code:3\n\n' + error);
});
await saveTimeStampDb(targetTree);
} else {
// 存在しない場合、エラーハンドリング
console.log('更新対象のsnapshotが存在しません。ツリー内容の変更は破棄されました。code:4');
Expand All @@ -129,17 +132,19 @@ export const useDatabase = () => {
};

// treesListをデータベースに保存する関数 ---------------------------------------------------------------------------
const saveTreesListDb = async (newTreesList: TreesList) => {
const saveTreesListDb = async (newTreesList: TreesList, noSaveTimestamp: boolean = false) => {
if (!uid) {
return;
}
try {
const userTreeListRef = ref(getDatabase(), `users/${uid}/treeList`);
await saveTimeStampDb();
await set(
userTreeListRef,
newTreesList.map((tree) => tree.id)
);
if (!noSaveTimestamp) {
await saveTimeStampDb(null);
}
} catch (error) {
handleError('ツリーリストの変更をデータベースに保存できませんでした。\n\n' + error);
}
Expand All @@ -152,8 +157,8 @@ export const useDatabase = () => {
}
try {
const treeNameRef = ref(getDatabase(), `trees/${targetTree}/name`);
await saveTimeStampDb();
await set(treeNameRef, editedTreeName);
await saveTimeStampDb(targetTree);
} catch (error) {
handleError('ツリー名の変更をデータベースに保存できませんでした。\n\n' + error);
}
Expand All @@ -163,8 +168,8 @@ export const useDatabase = () => {
const deleteTreeFromDb = async (targetTree: UniqueIdentifier) => {
const treeRef = ref(getDatabase(), `trees/${targetTree}`);
try {
await saveTimeStampDb();
await set(treeRef, null);
await saveTimeStampDb(null);
} catch (error) {
handleError('ツリーの削除に失敗しました。\n\n' + error);
}
Expand All @@ -185,15 +190,21 @@ export const useDatabase = () => {
if (treeTitle) {
treesListAccumulator = [...treesListAccumulator, { id: treeId, name: treeTitle }];
} else {
console.log('ツリー名が取得できませんでした。' + treeId + 'のツリーは削除されている可能性があります。');
missingTrees = missingTrees ? [...missingTrees, treeId] : [treeId];
}
});
await Promise.all(promises);

// DBの順序に基づいてtreesListAccumulatorを並び替え
const orderedTreesList = data
.map((treeId) => treesListAccumulator.find((t) => t.id === treeId))
.filter((t): t is TreesListItem => t !== undefined);

if (missingTrees.length > 0) {
await saveTreesListDb(orderedTreesList, true);
await showDialog('1つ以上のツリーが削除されたか、アクセス権限が変更されました。\n\n' + missingTrees.join('\n'), 'Information');
}

return orderedTreesList;
} else {
console.log('ツリーリストが見つかりませんでした。');
Expand Down
15 changes: 11 additions & 4 deletions src/hooks/useIndexedDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const useIndexedDb = () => {
const setHideDoneItems = useAppStateStore((state) => state.setHideDoneItems);
const quickMemoText = useAppStateStore((state) => state.quickMemoText);
const setQuickMemoText = useAppStateStore((state) => state.setQuickMemoText);
const setIsLoadedMemoFromDb = useAppStateStore((state) => state.setIsLoadedMemoFromDb);
const localTimestamp = useAppStateStore((state) => state.localTimestamp);
const setLocalTimestamp = useAppStateStore((state) => state.setLocalTimestamp);
const setTreesList = useTreeStateStore((state) => state.setTreesList);
Expand All @@ -40,6 +41,7 @@ export const useIndexedDb = () => {
return;
}
try {
console.log('syncDb');
setLocalTimestamp(Date.now());
await loadSettingsFromDb();
await loadQuickMemoFromDb();
Expand All @@ -59,10 +61,10 @@ export const useIndexedDb = () => {
if (allTreesData) {
await idb.treestate.clear();
for (const treeData of allTreesData) {
const treeTimestampRef = ref(getDatabase(), `trees/${treeData.id}/timestamp`);
await set(treeTimestampRef, localTimestamp);
const timestampV2Ref = ref(getDatabase(), `users/${uid}/timestampV2`);
await set(timestampV2Ref, localTimestamp);
if (treeData.timestamp === undefined || treeData.timestamp === null) {
const treeTimestampRef = ref(getDatabase(), `trees/${treeData.id}/timestamp`);
await set(treeTimestampRef, localTimestamp);
}
if (treeData.members) {
const functions = getFunctions();
const getUserEmails = httpsCallable(functions, 'getUserEmails');
Expand Down Expand Up @@ -91,6 +93,10 @@ export const useIndexedDb = () => {
}
}
}
const timestaampRef = ref(getDatabase(), `users/${uid}/timestamp`);
await set(timestaampRef, localTimestamp);
const timestampV2Ref = ref(getDatabase(), `users/${uid}/timestampV2`);
await set(timestampV2Ref, localTimestamp);
setTreesList(treesListFromDb);
} catch (error) {
handleError(error);
Expand Down Expand Up @@ -135,6 +141,7 @@ export const useIndexedDb = () => {
try {
const appState = await idb.appstate.get(1);
if (appState) {
setIsLoadedMemoFromDb(true);
setQuickMemoText(appState.quickMemo);
}
} catch (error) {
Expand Down
Loading

0 comments on commit c4d4f5c

Please sign in to comment.