Skip to content

Commit

Permalink
Refactor SettingsMenu and AppMain components
Browse files Browse the repository at this point in the history
  • Loading branch information
Jun-Murakami committed Feb 24, 2024
1 parent 6bc2022 commit d1acebf
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 21 deletions.
21 changes: 14 additions & 7 deletions src/components/AppMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ function AppMain({
setHideDoneItems(event.target.checked);
};

// ネストされたアイテムからアイテムを検索する
const containsItemId = (items: TreeItem[], itemId: UniqueIdentifier): boolean => {
return items.some((item) => item.id === itemId || containsItemId(item.children, itemId));
};

// ネストされたアイテムにアイテムを追加する
const addItemToNestedChildren = (items: TreeItem[], parentId: UniqueIdentifier, newItem: TreeItem): TreeItem[] => {
return items.map((item) => {
Expand Down Expand Up @@ -113,8 +118,8 @@ function AppMain({
}
setItems(newItems); // 更新されたアイテムの配列をセット
} else {
// 選択したアイテムのidがitemsの中に存在しない場合
if (!items.some((item) => item.id === lastSelectedItemId)) {
// itemsをchildren内を含めて再帰的に検索し、選択したアイテムのidが存在しない場合はツリーの最初に追加
if (!containsItemId(items, lastSelectedItemId)) {
const newItems = [...items]; // 現在のアイテムのコピーを作成
newItems.unshift(newTask); // 配列の先頭に追加
setItems(newItems); // 更新されたアイテムの配列をセット
Expand Down Expand Up @@ -142,29 +147,31 @@ function AppMain({
};

// ファイルを読み込んでアプリの状態を復元する
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) {
showDialog('ファイルが選択されていません。', 'Information');
await showDialog('ファイルが選択されていません。', 'Information');
return;
}

const result = await showDialog('現在のツリーは上書きされます。本当に復元しますか?', 'Confirmation Required', true);
if (!result) return;
const reader = new FileReader();
reader.onload = async (e) => {
const text = e.target?.result;
try {
const appState = JSON.parse(text as string);
if (!isValidAppState(appState)) {
showDialog('無効なファイル形式です。', 'Error');
await showDialog('無効なファイル形式です。', 'Error');
return;
} else {
setItems(appState.items);
setHideDoneItems(appState.hideDoneItems);
setDarkMode(appState.darkMode);
showDialog('ファイルが正常に読み込まれました。', 'Information');
await showDialog('ファイルが正常に読み込まれました。', 'Information');
}
} catch (error) {
showDialog('ファイルの読み込みに失敗しました。', 'Error');
await showDialog('ファイルの読み込みに失敗しました。', 'Error');
}
};
reader.readAsText(file);
Expand Down
4 changes: 2 additions & 2 deletions src/components/SettingsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export default function SettingsMenu({
</MenuItem>
</Tooltip>
{currentTree && (
<>
<Box>
<Divider />
<input type='file' ref={hiddenFileInput} onChange={handleFileUpload} style={{ display: 'none' }} accept='.json' />
<Tooltip title='バックアップをツリーに復元' placement='right'>
Expand Down Expand Up @@ -191,7 +191,7 @@ export default function SettingsMenu({
Backup
</MenuItem>
</Tooltip>
</>
</Box>
)}
<Divider />
<Tooltip title='ユーザーアカウントの削除' placement='right'>
Expand Down
32 changes: 25 additions & 7 deletions src/components/TreeSettingsAccordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export function TreeSettingsAccordion({
useEffect(() => {
if (isFocused && inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
setIsFocused(false);
}
}, [isFocused, setIsFocused]);
Expand Down Expand Up @@ -179,22 +180,31 @@ export function TreeSettingsAccordion({
marginTop: 0,
'& .MuiPaper-root': {
borderRadius: '0 0 8px 8px !important',
backgroundColor: 'transparent',
},
'& .MuiButtonBase-root': {
backgroundColor: 'transparent',
},
borderRadius: '0 0 8px 8px !important',
}}
expanded={isExpanded}
onChange={() => setIsExpanded(!isExpanded)}
onChange={() => {
setIsExpanded(!isExpanded);
{
!isExpanded && setIsFocused(true);
}
}}
>
<AccordionSummary
aria-controls='panel1a-content'
id='panel1a-header'
expandIcon={<ExpandMoreIcon />}
sx={{
'&.Mui-focused, &:hover': {
backgroundColor: 'transparent', // アクティブ状態の背景色を変更しない
backgroundColor: 'transparent',
},
height: 40,
paddingY: '30px',
paddingY: isExpanded ? '60px' : '30px',
paddingX: 2,
}}
>
Expand All @@ -207,7 +217,7 @@ export function TreeSettingsAccordion({
shrink: editedTreeName !== '',
}}
sx={{ zIndex: 1200, marginTop: 0, marginX: 2 }}
label='Tree Name'
label='Edit tree name & Press save button. (or Enter)'
fullWidth
size='small'
value={editedTreeName || ''}
Expand All @@ -219,9 +229,17 @@ export function TreeSettingsAccordion({
}
}}
InputProps={{
inputProps: {
style: { textAlign: 'center' },
},
endAdornment: (
<InputAdornment position='end'>
<IconButton sx={{ zIndex: 1200, right: 0 }} onClick={handleButtonClick} disabled={!editedTreeName}>
<IconButton
sx={{ zIndex: 1200, right: 0 }}
onClick={handleButtonClick}
disabled={!editedTreeName}
color='primary'
>
<SaveAsIcon />
</IconButton>
</InputAdornment>
Expand All @@ -236,7 +254,7 @@ export function TreeSettingsAccordion({
</Stack>
</AccordionSummary>
<AccordionDetails>
<Typography variant='body1' sx={{ marginTop: 0, ml: 2, textAlign: 'left' }}>
<Typography variant='body1' sx={{ marginTop: -1, ml: 2, textAlign: 'left' }}>
編集が許可されているメンバー
</Typography>
{currentTreeMembers && (
Expand Down Expand Up @@ -271,7 +289,7 @@ export function TreeSettingsAccordion({
width: '100%',
display: 'flex',
justifyContent: 'flex-end',
marginTop: 2,
marginTop: 1,
}}
>
<Button variant={'outlined'} sx={{ mr: 2 }} startIcon={<AddIcon />} color='inherit' onClick={handleAddUserToTree}>
Expand Down
43 changes: 38 additions & 5 deletions src/hooks/useTreeManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const useTreeManagement = (
setIsFocused: React.Dispatch<React.SetStateAction<boolean>>
) => {
const [isLoadedItemsFromExternal, setIsLoadedItemsFromExternal] = useState(false);
const [isLoadedTreesListFromExternal, setIsLoadedTreesListFromExternal] = useState(false);
const [MissingTrees, setMissingTrees] = useState<string[] | null>(null);
const showDialog = useDialogStore((state) => state.showDialog);

Expand Down Expand Up @@ -83,9 +84,11 @@ export const useTreeManagement = (

Promise.all(promises).then(async (): Promise<void> => {
setTreesList(treesListAccumulator); // 全てのプロミスが解決された後に更新
setIsLoadedTreesListFromExternal(true);
});
} else {
setTreesList([]); // スナップショットが存在しない場合は空をセット
setIsLoadedTreesListFromExternal(true);
}
});

Expand Down Expand Up @@ -211,14 +214,18 @@ export const useTreeManagement = (
// コンポーネントがアンマウントされるか、依存配列の値が変更された場合にタイマーをクリア
return () => clearTimeout(debounceSave);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [items, isLoadedItemsFromExternal, handleError]);
}, [items, handleError]);


// treesListの変更をデータベースに保存
useEffect(() => {
const debounceSave = setTimeout(() => {
const user = getAuth().currentUser;
if (!user || !treesList) {
if (!user || treesList.length === 0) {
return;
}
if (isLoadedTreesListFromExternal) {
setIsLoadedTreesListFromExternal(false);
return;
}
try {
Expand All @@ -232,8 +239,31 @@ export const useTreeManagement = (

// コンポーネントがアンマウントされるか、依存配列の値が変更された場合にタイマーをクリア
return () => clearTimeout(debounceSave);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [treesList, handleError]);

// ツリー名の変更を監視→変更されたらツリーリストを更新
useEffect(() => {
const db = getDatabase();
const unsubscribeFunctions = treesList.map(tree => {
const treeNameRef = ref(db, `trees/${tree.id}/name`);
return onValue(treeNameRef, (snapshot) => {
if (snapshot.exists()) {
setTreesList((currentTreesList) =>
currentTreesList.map((t) =>
t.id === tree.id ? { ...t, name: snapshot.val() } : t
)
);
setIsLoadedTreesListFromExternal(true);
}
});
});

return () => {
unsubscribeFunctions.forEach(unsubscribe => unsubscribe());
};
}, [treesList, setTreesList]);


// 見つからないツリーがあった場合、ユーザーに通知してデータベース側を更新
useEffect(() => {
Expand Down Expand Up @@ -291,7 +321,7 @@ export const useTreeManagement = (
}, [showDialog]);


//ツリーを削除する
//ツリーを削除する関数
const deleteTree = async (treeId: string) => {
const user = getAuth().currentUser;
if (!user) {
Expand All @@ -318,7 +348,7 @@ export const useTreeManagement = (
}
};

// 新しいツリーを作成する
// 新しいツリーを作成する関数
const handleCreateNewTree = async () => {
const user = getAuth().currentUser;
if (!user) {
Expand Down Expand Up @@ -360,7 +390,10 @@ export const useTreeManagement = (
}
});
setIsExpanded(true);
setIsFocused(true);
// 0.2秒後にフォーカスをセット
setTimeout(() => {
setIsFocused(true);
}, 200);
};

return { saveCurrentTreeName, deleteTree, handleCreateNewTree };
Expand Down

0 comments on commit d1acebf

Please sign in to comment.