Skip to content

Commit 61b17e5

Browse files
authored
Merge pull request #197 from us3r64bit/develop
Implement import/Export Bookmarks
2 parents 9d5b39d + 8b06ee3 commit 61b17e5

File tree

2 files changed

+101
-9
lines changed

2 files changed

+101
-9
lines changed

src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useRef, useState } from 'react'
12
import { BiBookmarkMinus } from 'react-icons/bi'
23
import toast from 'react-simple-toasts'
34
import { CardLink } from 'src/components/Elements'
@@ -60,17 +61,80 @@ const BookmarkItem = ({ item, appendRef = false }: BookmarkItemProps) => {
6061
}
6162

6263
export const BookmarkSettings = () => {
63-
const { userBookmarks } = useBookmarks()
64+
const inputFile = useRef<HTMLInputElement | null>(null)
65+
const {initState, userBookmarks } = useBookmarks()
66+
67+
const importBookmarks = () => {
68+
inputFile.current?.click()
69+
}
70+
71+
const exportBookmarks = () => {
72+
const blob = new Blob([JSON.stringify(userBookmarks, null, 2)], {
73+
type: 'application/json',
74+
})
75+
const downloadURL = URL.createObjectURL(blob);
76+
const link = document.createElement("a");
77+
link.href = downloadURL;
78+
link.download = "hackertabBookmarks";
79+
link.click();
80+
toast('Your bookmarks have been successfully exported', { theme: 'defaultToast' })
81+
}
82+
const handleFileChange = (event: any) => {
83+
const file = event.target.files?.[0];
84+
if (file) {
85+
const reader = new FileReader()
86+
reader.onload = () => {
87+
const importData: BookmarkedPost[] = JSON.parse(reader.result as string);
88+
const validatedData = importData.filter(
89+
(data: BookmarkedPost) =>
90+
data.title &&
91+
data.url &&
92+
!userBookmarks.some((bm) => bm.title === data.title && bm.url === data.url))
93+
.map((data) => ({
94+
title: data.title,
95+
url: data.url,
96+
source: data.source || '',
97+
sourceType: data.sourceType || '',
98+
}));
99+
initState({
100+
userBookmarks: [...userBookmarks, ...validatedData],
101+
});
102+
toast('Your bookmarks have been successfully imported', { theme: 'defaultToast' })
103+
}
104+
reader.readAsText(file)
105+
}
106+
}
107+
64108

65109
return (
66-
<SettingsContentLayout
67-
title="Bookmarks"
68-
description="Find all your bookmarks here. You can remove a bookmark by clicking on the remove icon.">
69-
<div className="bookmarks">
70-
{userBookmarks.map((bm) => (
71-
<BookmarkItem item={bm} key={bm.url} />
72-
))}
110+
<>
111+
<div className="btn-group">
112+
<div>
113+
<input
114+
type="file"
115+
id="file"
116+
ref={inputFile}
117+
accept="application/json"
118+
style={{ display: 'none' }}
119+
onChange={handleFileChange}
120+
/>
121+
<button className="notbtn btn" onClick={() => importBookmarks()}>
122+
Import
123+
</button>
124+
</div>
125+
<button className="notbtn btn" onClick={() => exportBookmarks()}>
126+
Export
127+
</button>
73128
</div>
74-
</SettingsContentLayout>
129+
<SettingsContentLayout
130+
title="Bookmarks"
131+
description="Find all your bookmarks here. You can remove a bookmark by clicking on the remove icon.">
132+
<div className="bookmarks">
133+
{userBookmarks.map((bm) => (
134+
<BookmarkItem item={bm} key={bm.url} />
135+
))}
136+
</div>
137+
</SettingsContentLayout>
138+
</>
75139
)
76140
}

src/features/settings/components/BookmarkSettings/bookmarkSettings.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,31 @@
5353
align-items: center;
5454
justify-content: center;
5555
}
56+
57+
/* Export/Import Bookmark Buttons */
58+
59+
/* removing that ugly default button design */
60+
.notbtn {
61+
background: none;
62+
color: inherit;
63+
border: none;
64+
padding: 0;
65+
font: inherit;
66+
cursor: pointer;
67+
outline: inherit;
68+
}
69+
70+
.btn-group {
71+
padding: 10px;
72+
display: flex;
73+
}
74+
75+
.btn {
76+
border-radius: 12px;
77+
padding: 6px 12px;
78+
margin-right: 5px;
79+
background-color: var(--chip-background);
80+
}
81+
.btn:hover {
82+
filter: brightness(85%);
83+
}

0 commit comments

Comments
 (0)