diff --git a/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx b/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx index 86ca31d3..f548858a 100644 --- a/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx +++ b/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx @@ -1,3 +1,4 @@ +import { useRef, useState } from 'react' import { BiBookmarkMinus } from 'react-icons/bi' import toast from 'react-simple-toasts' import { CardLink } from 'src/components/Elements' @@ -60,17 +61,84 @@ const BookmarkItem = ({ item, appendRef = false }: BookmarkItemProps) => { } export const BookmarkSettings = () => { - const { userBookmarks } = useBookmarks() + const inputFile = useRef<HTMLInputElement | null>(null) + const {initState, userBookmarks } = useBookmarks() + + const ImportBookmarks = () => { + inputFile.current?.click() + } + + const ExportBookmarks = () => { + const blob = new Blob([JSON.stringify(userBookmarks, null, 2)], { + type: 'application/json', + }) + const downloadURL = URL.createObjectURL(blog); + const link = document.createElement("a"); + link.href = downloadURL; + link.download = "hackertabBookmarks"; + link.click(); + } + const handleFileChange = (event: any) => { + if (event.target.files[0]) { + const reader = new FileReader() + reader.onload = () => { + const importData = JSON.parse(reader.result as string) + // Check for duplicates + const uniqueImportData = importData?.filter( + (data: BookmarkedPost) => + !userBookmarks.some((bm) => bm.title === data.title && bm.url === data.url) + ) + // Check if 'title' and 'url' exists or not + const validatedData = uniqueImportData?.map((data: BookmarkedPost) => { + if(!data.title || !data.url){ + // skip invalid data + return null; + } + return { + title: data.title, + url: data.url, + source: data.source || '', + sourceType: data.sourceType || '', + } + }).filter(Boolean) + + initState({ + userBookmarks: [...userBookmarks, ...validatedData], + }); + } + reader.readAsText(event.target.files[0]) + } + } + return ( - <SettingsContentLayout - title="Bookmarks" - description="Find all your bookmarks here. You can remove a bookmark by clicking on the remove icon."> - <div className="bookmarks"> - {userBookmarks.map((bm) => ( - <BookmarkItem item={bm} key={bm.url} /> - ))} + <> + <div className="btn-group"> + <div> + <input + type="file" + id="file" + ref={inputFile} + style={{ display: 'none' }} + onChange={handleFileChange} + /> + <button id="OpenImgUpload" className="notbtn btn" onClick={() => ImportBookmarks()}> + Import + </button> + </div> + <button className="notbtn btn" onClick={() => ExportBookmarks()}> + Export + </button> </div> - </SettingsContentLayout> + <SettingsContentLayout + title="Bookmarks" + description="Find all your bookmarks here. You can remove a bookmark by clicking on the remove icon."> + <div className="bookmarks"> + {userBookmarks.map((bm) => ( + <BookmarkItem item={bm} key={bm.url} /> + ))} + </div> + </SettingsContentLayout> + </> ) } diff --git a/src/features/settings/components/BookmarkSettings/bookmarkSettings.css b/src/features/settings/components/BookmarkSettings/bookmarkSettings.css index 6775a57c..889f7920 100644 --- a/src/features/settings/components/BookmarkSettings/bookmarkSettings.css +++ b/src/features/settings/components/BookmarkSettings/bookmarkSettings.css @@ -53,3 +53,31 @@ align-items: center; justify-content: center; } + +/* Export/Import Bookmark Buttons */ + +/* removing that ugly default button design */ +.notbtn { + background: none; + color: inherit; + border: none; + padding: 0; + font: inherit; + cursor: pointer; + outline: inherit; +} + +.btn-group { + padding: 10px; + display: flex; +} + +.btn { + border-radius: 12px; + padding: 6px 12px; + margin-right: 5px; + background-color: var(--chip-background); +} +.btn:hover { + filter: brightness(85%); +}