diff --git a/src/components/Layout/SettingsContentLayout/SettingsContentLayout.tsx b/src/components/Layout/SettingsContentLayout/SettingsContentLayout.tsx
index fb6b1c31..cd2b596f 100644
--- a/src/components/Layout/SettingsContentLayout/SettingsContentLayout.tsx
+++ b/src/components/Layout/SettingsContentLayout/SettingsContentLayout.tsx
@@ -4,18 +4,24 @@ type SettingsContentLayoutProps = {
title: string
description: string
children: React.ReactNode
+ actions?: React.ReactNode
}
export const SettingsContentLayout = ({
title,
description,
+ actions,
children,
}: SettingsContentLayoutProps) => {
return (
- {title}
- {description}
+
+
{title}
+
{description}
+
+
+ {actions && {actions}
}
{children}
diff --git a/src/components/Layout/SettingsContentLayout/settingsContentLayout.css b/src/components/Layout/SettingsContentLayout/settingsContentLayout.css
index 07437110..a79379a8 100644
--- a/src/components/Layout/SettingsContentLayout/settingsContentLayout.css
+++ b/src/components/Layout/SettingsContentLayout/settingsContentLayout.css
@@ -15,23 +15,33 @@
gap: 16px;
}
.settingsContent header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.settingsContent .settingsHeader {
display: flex;
flex-direction: column;
row-gap: 8px;
}
-.settingsContent header .title {
+.settingsContent .settingsHeader .title {
font-size: 24px;
margin: 0;
padding: 0;
color: var(--primary-text-color);
}
-.settingsContent header .description {
+.settingsContent .settingsHeader .description {
font-size: 14px;
margin: 0;
padding: 0;
color: var(--secondary-text-color);
}
-
+.settingsContent .actions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
@media only screen and (max-width: 768px) {
.settingsContent {
padding: 16px;
diff --git a/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx b/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx
index 86ca31d3..3683e9ed 100644
--- a/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx
+++ b/src/features/settings/components/BookmarkSettings/BookmarkSettings.tsx
@@ -1,4 +1,6 @@
+import { useRef } from 'react'
import { BiBookmarkMinus } from 'react-icons/bi'
+import { RiFileDownloadFill, RiFileUploadFill } from 'react-icons/ri'
import toast from 'react-simple-toasts'
import { CardLink } from 'src/components/Elements'
import { SettingsContentLayout } from 'src/components/Layout/SettingsContentLayout'
@@ -60,17 +62,82 @@ const BookmarkItem = ({ item, appendRef = false }: BookmarkItemProps) => {
}
export const BookmarkSettings = () => {
- const { userBookmarks } = useBookmarks()
+ const inputFile = useRef(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(blob)
+ const link = document.createElement('a')
+ link.href = downloadURL
+ link.download = 'hackertabBookmarks'
+ link.click()
+ }
+
+ const handleFileChange = (event: any) => {
+ const file = event.target.files?.[0]
+ if (file) {
+ const reader = new FileReader()
+ reader.onload = () => {
+ const importData: BookmarkedPost[] = JSON.parse(reader.result as string)
+ const validatedData = importData
+ .filter(
+ (data: BookmarkedPost) =>
+ data.title &&
+ data.url &&
+ !userBookmarks.some((bm) => bm.title === data.title && bm.url === data.url)
+ )
+ .map((data) => ({
+ title: data.title,
+ url: data.url,
+ source: data.source || '',
+ sourceType: data.sourceType || '',
+ }))
+ initState({
+ userBookmarks: [...userBookmarks, ...validatedData],
+ })
+ toast('Your bookmarks have been successfully imported', { theme: 'defaultToast' })
+ }
+ reader.readAsText(file)
+ }
+ }
return (
-
-
- {userBookmarks.map((bm) => (
-
- ))}
-
-
+ <>
+
+
+
+
+ >
+ }>
+
+ {userBookmarks.map((bm) => (
+
+ ))}
+
+
+ >
)
}
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%);
+}
diff --git a/src/features/settings/components/SearchEngineSettings.tsx b/src/features/settings/components/SearchEngineSettings.tsx
index ebf2d6ee..f3cc2154 100644
--- a/src/features/settings/components/SearchEngineSettings.tsx
+++ b/src/features/settings/components/SearchEngineSettings.tsx
@@ -49,10 +49,12 @@ export const SearchEngineSettings = () => {
<>
>
diff --git a/src/features/settings/components/SourceSettings.tsx b/src/features/settings/components/SourceSettings.tsx
index a1099179..b9da4deb 100644
--- a/src/features/settings/components/SourceSettings.tsx
+++ b/src/features/settings/components/SourceSettings.tsx
@@ -69,11 +69,13 @@ export const SourceSettings = () => {
<>
>