diff --git a/functions/src/index.ts b/functions/src/index.ts index 6141010..3fa6242 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -73,6 +73,19 @@ exports.addUserToTree = functions.https.onCall(async (data: { email: string; tre return currentMembers; } }); + const treeMembersRefV2 = admin.database().ref(`trees/${treeId}/membersV2`); + await treeMembersRefV2.transaction((currentMembers: { [key: string]: string | boolean } | null) => { + if (currentMembers === null) { + const newMembers: { [key: string]: string } = {}; + newMembers[userId] = email; // 新しいメンバーとして追加 + return newMembers; + } else { + if (!Object.prototype.hasOwnProperty.call(currentMembers, userId)) { + currentMembers[userId] = email; // メンバーが存在しなければ追加 + } + return currentMembers; + } + }); // users/$userId/treeListにtreeIdを追加 const userTreeListRef = admin.database().ref(`users/${userId}/treeList`); @@ -86,6 +99,10 @@ 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); @@ -138,6 +155,19 @@ exports.removeUserFromTree = functions.https.onCall(async (data: { treeId: strin } } }); + const treeMembersRefV2 = admin.database().ref(`trees/${treeId}/membersV2`); + await treeMembersRefV2.transaction((currentMembers: { [key: string]: string } | null) => { + if (currentMembers === null) { + return currentMembers; // 何もしない + } else { + if (Object.prototype.hasOwnProperty.call(currentMembers, userId)) { + delete currentMembers[userId]; // userIdをキーとして持つプロパティを削除 + return currentMembers; + } else { + return currentMembers; // ユーザーが見つからない場合は何もしない + } + } + }); // users/$userId/treeListからtreeIdを削除 const userTreeListRef = admin.database().ref(`users/${userId}/treeList`); @@ -155,6 +185,10 @@ 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); @@ -187,10 +221,26 @@ exports.createNewTree = functions.https.onCall(async (data: { items: ServerTreeI const db = admin.database(); const treesRef = db.ref('trees'); const newTreeRef = treesRef.push(); + const emails = await Promise.all( + Object.keys(members).map(async (uid) => { + const userRecord = await admin.auth().getUser(uid); + return userRecord.email; + }) + ); + const membersV2: { [key: string]: string } = {}; + Object.keys(members).forEach((uid, index) => { + const email = emails[index]; + if (email) { + membersV2[uid] = email; + } else { + throw new Error('Email not found for UID: ' + uid); + } + }); await newTreeRef.set({ items: items, name: name, members: members, + membersV2: membersV2, }); return newTreeRef.key; } catch (error) { @@ -217,4 +267,25 @@ exports.copyFileInStorage = functions.https.onCall(async (data: { sourcePath: st console.error('Error copying file:', error); throw new functions.https.HttpsError('unknown', 'Failed to copy file'); } +}); + +// 指定されたuidリストを指定されたタイムスタンプで更新 +exports.updateTimestamps = functions.https.onCall(async (data: { uids: string[], timestamp: number }) => { + const { uids, timestamp } = data; + if (!uids || !Array.isArray(uids) || !timestamp) { + throw new functions.https.HttpsError('invalid-argument', 'The function must be called with valid "uids" and "timestamp".'); + } + try { + const db = admin.database(); + await Promise.all( + uids.map(async (uid) => { + const userRef = db.ref(`users/${uid}`); + await userRef.update({ timestamp: timestamp }); + }) + ); + return { success: true }; + } catch (error) { + console.error('Error updating timestamps:', error); + throw new functions.https.HttpsError('unknown', 'Failed to update timestamps'); + } }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5b2e5cd..b3e9887 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tasktree-s", - "version": "2.0.0", + "version": "1.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tasktree-s", - "version": "2.0.0", + "version": "1.1.2", "dependencies": { "@capacitor-firebase/authentication": "^5.4.1", "@capacitor/android": "^5.7.4", @@ -27,6 +27,8 @@ "@fontsource/m-plus-1p": "^5.0.18", "@mui/icons-material": "^5.15.15", "@mui/material": "^5.15.15", + "dexie": "^4.0.4", + "dexie-react-hooks": "^1.1.7", "firebase": "^10.6.0", "immer": "^10.0.4", "lodash": "^4.17.21", @@ -4542,6 +4544,21 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/dexie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.4.tgz", + "integrity": "sha512-wFzwWSUdi+MC3jiFeQcCp9nInR7EaX8edzYY+4wmiITkQAiSnHpe4Wo2o5Ce5tJZe2nqt7mLW91MsW4GYx3ziQ==" + }, + "node_modules/dexie-react-hooks": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/dexie-react-hooks/-/dexie-react-hooks-1.1.7.tgz", + "integrity": "sha512-Lwv5W0Hk+uOW3kGnsU9GZoR1er1B7WQ5DSdonoNG+focTNeJbHW6vi6nBoX534VKI3/uwHebYzSw1fwY6a7mTw==", + "peerDependencies": { + "@types/react": ">=16", + "dexie": "^3.2 || ^4.0.1-alpha", + "react": ">=16" + } + }, "node_modules/dezalgo": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", diff --git a/package.json b/package.json index 5ce7c1c..57df48e 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "@fontsource/m-plus-1p": "^5.0.18", "@mui/icons-material": "^5.15.15", "@mui/material": "^5.15.15", + "dexie": "^4.0.4", + "dexie-react-hooks": "^1.1.7", "firebase": "^10.6.0", "immer": "^10.0.4", "lodash": "^4.17.21", diff --git a/src/components/HomePage.tsx b/src/components/HomePage.tsx index 2a59689..a0be748 100644 --- a/src/components/HomePage.tsx +++ b/src/components/HomePage.tsx @@ -219,10 +219,10 @@ export function HomePage() { Appleでログイン