mirror of
https://github.com/linkwarden/browser-extension.git
synced 2026-06-23 04:10:26 +00:00
bug fix
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"name": "Linkwarden",
|
||||
"description": "The browser extension for Linkwarden.",
|
||||
"homepage_url": "https://linkwarden.app/",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"action": {
|
||||
"default_popup": "./index.html",
|
||||
"default_icon": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "Linkwarden",
|
||||
"description": "The browser extension for Linkwarden.",
|
||||
"homepage_url": "https://linkwarden.app/",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"browser_action": {
|
||||
"default_popup": "./index.html",
|
||||
"default_icon": {
|
||||
|
||||
+182
-225
@@ -17,7 +17,7 @@ import { Button } from './ui/Button.tsx';
|
||||
import { TagInput } from './TagInput.tsx';
|
||||
import { Textarea } from './ui/Textarea.tsx';
|
||||
import {
|
||||
getCurrentLinkItem,
|
||||
checkDuplicatedItem,
|
||||
getCurrentTabInfo,
|
||||
updateBadge,
|
||||
} from '../lib/utils.ts';
|
||||
@@ -40,16 +40,13 @@ import {
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
} from './ui/Command.tsx';
|
||||
import { bookmarkMetadata, saveLinksInCache } from '../lib/cache.ts';
|
||||
import { saveLinksInCache } from '../lib/cache.ts';
|
||||
import { Checkbox } from './ui/CheckBox.tsx';
|
||||
import { Label } from './ui/Label.tsx';
|
||||
|
||||
let configured = false;
|
||||
let baseUrl = '';
|
||||
let duplicated = false;
|
||||
const BookmarkForm = () => {
|
||||
const [savedLwItem, setSavedLwItem] = useState<
|
||||
bookmarkMetadata | false | void
|
||||
>(undefined);
|
||||
const [openOptions, setOpenOptions] = useState<boolean>(false);
|
||||
const [openCollections, setOpenCollections] = useState<boolean>(false);
|
||||
const [uploadImage, setUploadImage] = useState<boolean>(false);
|
||||
@@ -110,9 +107,6 @@ const BookmarkForm = () => {
|
||||
return;
|
||||
},
|
||||
onSuccess: () => {
|
||||
getCurrentLinkItem().then((item) => {
|
||||
setSavedLwItem(item);
|
||||
});
|
||||
// Update badge to show link is saved
|
||||
getCurrentTabInfo().then(({ id }) => {
|
||||
updateBadge(id);
|
||||
@@ -143,7 +137,7 @@ const BookmarkForm = () => {
|
||||
});
|
||||
const getConfigUse = async () => {
|
||||
configured = await isConfigured();
|
||||
setSavedLwItem(await getCurrentLinkItem());
|
||||
duplicated = await checkDuplicatedItem();
|
||||
};
|
||||
getConfigUse();
|
||||
}, [form]);
|
||||
@@ -151,12 +145,7 @@ const BookmarkForm = () => {
|
||||
useEffect(() => {
|
||||
const syncBookmarks = async () => {
|
||||
try {
|
||||
const {
|
||||
syncBookmarks,
|
||||
baseUrl: configBaseUrl,
|
||||
defaultCollection,
|
||||
} = await getConfig();
|
||||
baseUrl = configBaseUrl;
|
||||
const { syncBookmarks, baseUrl, defaultCollection } = await getConfig();
|
||||
form.setValue('collection', {
|
||||
name: defaultCollection,
|
||||
});
|
||||
@@ -222,178 +211,171 @@ const BookmarkForm = () => {
|
||||
<FormField
|
||||
control={control}
|
||||
name="collection"
|
||||
render={({ field }) =>
|
||||
savedLwItem === false ? (
|
||||
<FormItem className={`my-2`}>
|
||||
<FormLabel>Collection</FormLabel>
|
||||
<div className="min-w-full inset-x-0">
|
||||
<Popover
|
||||
open={openCollections}
|
||||
onOpenChange={setOpenCollections}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openCollections}
|
||||
className={
|
||||
'w-full justify-between bg-neutral-100 dark:bg-neutral-900'
|
||||
}
|
||||
>
|
||||
{loadingCollections
|
||||
? 'Loading'
|
||||
: field.value?.name
|
||||
? collections?.find(
|
||||
(collection: { name: string }) =>
|
||||
collection.name === field.value?.name
|
||||
)?.name || form.getValues('collection')?.name
|
||||
: 'Select a collection...'}
|
||||
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
render={({ field }) => (
|
||||
<FormItem className={`my-2`}>
|
||||
<FormLabel>Collection</FormLabel>
|
||||
<div className="min-w-full inset-x-0">
|
||||
<Popover
|
||||
open={openCollections}
|
||||
onOpenChange={setOpenCollections}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openCollections}
|
||||
className={
|
||||
'w-full justify-between bg-neutral-100 dark:bg-neutral-900'
|
||||
}
|
||||
>
|
||||
{loadingCollections
|
||||
? 'Loading'
|
||||
: field.value?.name
|
||||
? collections?.find(
|
||||
(collection: { name: string }) =>
|
||||
collection.name === field.value?.name
|
||||
)?.name || form.getValues('collection')?.name
|
||||
: 'Select a collection...'}
|
||||
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
|
||||
{!openOptions && openCollections ? (
|
||||
<div
|
||||
className={`fade-up min-w-full p-0 overflow-y-auto ${
|
||||
openCollections
|
||||
? 'fixed inset-0 w-full h-full z-50 bg-white'
|
||||
: ''
|
||||
}`}
|
||||
{!openOptions && openCollections ? (
|
||||
<div
|
||||
className={`fade-up min-w-full p-0 overflow-y-auto ${
|
||||
openCollections
|
||||
? 'fixed inset-0 w-full h-full z-50 bg-white'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<Button
|
||||
className="absolute top-1 right-1 bg-transparent hover:bg-transparent hover:opacity-50 transition-colors ease-in-out duration-200"
|
||||
onClick={() => setOpenCollections(false)}
|
||||
>
|
||||
<Button
|
||||
className="absolute top-1 right-1 bg-transparent hover:bg-transparent hover:opacity-50 transition-colors ease-in-out duration-200"
|
||||
onClick={() => setOpenCollections(false)}
|
||||
>
|
||||
<X
|
||||
className={`h-4 w-4 text-black dark:text-white`}
|
||||
/>
|
||||
</Button>
|
||||
<Command className="flex-grow min-w-full dropdown-content rounded-none">
|
||||
<CommandInput
|
||||
className="min-w-[280px]"
|
||||
placeholder="Search Collection..."
|
||||
autoFocus={true}
|
||||
/>
|
||||
<CommandEmpty>No Collection found.</CommandEmpty>
|
||||
{Array.isArray(collections) && (
|
||||
<CommandGroup className="w-full overflow-y-auto">
|
||||
{isLoading ? (
|
||||
<CommandItem
|
||||
value="Getting collections..."
|
||||
key="Getting collections..."
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
name: 'Unorganized',
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
Unorganized
|
||||
</CommandItem>
|
||||
) : (
|
||||
collections?.map(
|
||||
(collection: {
|
||||
name: string;
|
||||
id: number;
|
||||
ownerId: number;
|
||||
pathname: string;
|
||||
}) => (
|
||||
<CommandItem
|
||||
value={collection.name}
|
||||
key={collection.id}
|
||||
className="cursor-pointer flex flex-col items-start justify-start"
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
ownerId: collection.ownerId,
|
||||
id: collection.id,
|
||||
name: collection.name,
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
<p>{collection.name}</p>
|
||||
<p className="text-xs text-neutral-500">
|
||||
{collection.pathname}
|
||||
</p>
|
||||
</CommandItem>
|
||||
)
|
||||
<X className={`h-4 w-4 text-black dark:text-white`} />
|
||||
</Button>
|
||||
<Command className="flex-grow min-w-full dropdown-content rounded-none">
|
||||
<CommandInput
|
||||
className="min-w-[280px]"
|
||||
placeholder="Search Collection..."
|
||||
/>
|
||||
<CommandEmpty>No Collection found.</CommandEmpty>
|
||||
{Array.isArray(collections) && (
|
||||
<CommandGroup className="w-full overflow-y-auto">
|
||||
{isLoading ? (
|
||||
<CommandItem
|
||||
value="Getting collections..."
|
||||
key="Getting collections..."
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
name: 'Unorganized',
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
Unorganized
|
||||
</CommandItem>
|
||||
) : (
|
||||
collections?.map(
|
||||
(collection: {
|
||||
name: string;
|
||||
id: number;
|
||||
ownerId: number;
|
||||
pathname: string;
|
||||
}) => (
|
||||
<CommandItem
|
||||
value={collection.name}
|
||||
key={collection.id}
|
||||
className="cursor-pointer flex flex-col items-start justify-start"
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
ownerId: collection.ownerId,
|
||||
id: collection.id,
|
||||
name: collection.name,
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
<p>{collection.name}</p>
|
||||
<p className="text-xs text-neutral-500">
|
||||
{collection.pathname}
|
||||
</p>
|
||||
</CommandItem>
|
||||
)
|
||||
)}
|
||||
</CommandGroup>
|
||||
)}
|
||||
</Command>
|
||||
</div>
|
||||
) : openOptions && openCollections ? (
|
||||
<PopoverContent
|
||||
className={`min-w-full p-0 overflow-y-auto max-h-[200px]`}
|
||||
>
|
||||
<Command className="flex-grow min-w-full dropdown-content">
|
||||
<CommandInput
|
||||
className="min-w-[280px]"
|
||||
placeholder="Search collection..."
|
||||
/>
|
||||
<CommandEmpty>No Collection found.</CommandEmpty>
|
||||
{Array.isArray(collections) && (
|
||||
<CommandGroup className="w-full">
|
||||
{isLoading ? (
|
||||
<CommandItem
|
||||
value="Getting collections..."
|
||||
key="Getting collections..."
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
name: 'Unorganized',
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
Unorganized
|
||||
</CommandItem>
|
||||
) : (
|
||||
collections?.map(
|
||||
(collection: {
|
||||
name: string;
|
||||
id: number;
|
||||
ownerId: number;
|
||||
pathname: string;
|
||||
}) => (
|
||||
<CommandItem
|
||||
value={collection.name}
|
||||
key={collection.id}
|
||||
className="cursor-pointer flex flex-col items-start justify-start"
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
ownerId: collection.ownerId,
|
||||
id: collection.id,
|
||||
name: collection.name,
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
<p>{collection.name}</p>
|
||||
<p className="text-xs text-neutral-500">
|
||||
{collection.pathname}
|
||||
</p>
|
||||
</CommandItem>
|
||||
)
|
||||
)
|
||||
)}
|
||||
</CommandGroup>
|
||||
)}
|
||||
</Command>
|
||||
</div>
|
||||
) : openOptions && openCollections ? (
|
||||
<PopoverContent
|
||||
className={`min-w-full p-0 overflow-y-auto max-h-[200px]`}
|
||||
>
|
||||
<Command className="flex-grow min-w-full dropdown-content">
|
||||
<CommandInput
|
||||
className="min-w-[280px]"
|
||||
placeholder="Search collection..."
|
||||
/>
|
||||
<CommandEmpty>No Collection found.</CommandEmpty>
|
||||
{Array.isArray(collections) && (
|
||||
<CommandGroup className="w-full">
|
||||
{isLoading ? (
|
||||
<CommandItem
|
||||
value="Getting collections..."
|
||||
key="Getting collections..."
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
name: 'Unorganized',
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
Unorganized
|
||||
</CommandItem>
|
||||
) : (
|
||||
collections?.map(
|
||||
(collection: {
|
||||
name: string;
|
||||
id: number;
|
||||
ownerId: number;
|
||||
pathname: string;
|
||||
}) => (
|
||||
<CommandItem
|
||||
value={collection.name}
|
||||
key={collection.id}
|
||||
className="cursor-pointer flex flex-col items-start justify-start"
|
||||
onSelect={() => {
|
||||
form.setValue('collection', {
|
||||
ownerId: collection.ownerId,
|
||||
id: collection.id,
|
||||
name: collection.name,
|
||||
});
|
||||
setOpenCollections(false);
|
||||
}}
|
||||
>
|
||||
<p>{collection.name}</p>
|
||||
<p className="text-xs text-neutral-500">
|
||||
{collection.pathname}
|
||||
</p>
|
||||
</CommandItem>
|
||||
)
|
||||
)}
|
||||
</CommandGroup>
|
||||
)}
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
) : undefined}
|
||||
</Popover>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
) : (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
)
|
||||
)}
|
||||
</CommandGroup>
|
||||
)}
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
) : undefined}
|
||||
</Popover>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
{openOptions && savedLwItem === false && (
|
||||
{openOptions && (
|
||||
<div className="details list-none space-y-5 pt-2">
|
||||
{tagsError ? <p>There was an error...</p> : null}
|
||||
<FormField
|
||||
@@ -460,50 +442,25 @@ const BookmarkForm = () => {
|
||||
</Label>
|
||||
</div>
|
||||
)}
|
||||
{savedLwItem === false ? (
|
||||
<div className="flex justify-between items-center mt-6">
|
||||
<div
|
||||
className="inline-flex select-none items-center justify-center rounded-md text-sm font-medium ring-offset-background
|
||||
transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring
|
||||
focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50
|
||||
hover:bg-accent hover:text-accent-foreground hover:cursor-pointer p-2"
|
||||
onClick={() => setOpenOptions((prevState) => !prevState)}
|
||||
>
|
||||
{openOptions ? 'Hide' : 'More'} Options
|
||||
</div>
|
||||
<Button disabled={isLoading} type="submit">
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
{duplicated && (
|
||||
<p className="text-muted text-zinc-600 dark:text-zinc-400 mt-2">
|
||||
You already have this link saved.
|
||||
</p>
|
||||
)}
|
||||
{savedLwItem ? (
|
||||
<div>
|
||||
<p className="text-muted text-zinc-600 dark:text-zinc-400 mt-4">
|
||||
You already have this link saved.
|
||||
</p>
|
||||
<div className="flex justify-end mt-6">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
window.open(
|
||||
baseUrl +
|
||||
'/search?q=' +
|
||||
encodeURIComponent(savedLwItem.url),
|
||||
'_blank'
|
||||
);
|
||||
window.close();
|
||||
}}
|
||||
>
|
||||
Show in Linkwarden
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center mt-4">
|
||||
<div
|
||||
className="inline-flex select-none items-center justify-center rounded-md text-sm font-medium ring-offset-background
|
||||
transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring
|
||||
focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50
|
||||
hover:bg-accent hover:text-accent-foreground hover:cursor-pointer p-2"
|
||||
onClick={() => setOpenOptions((prevState) => !prevState)}
|
||||
>
|
||||
{openOptions ? 'Hide' : 'More'} Options
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<Button disabled={isLoading} type="submit">
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
<Toaster />
|
||||
|
||||
@@ -2,10 +2,12 @@ import { FC } from 'react';
|
||||
import { openOptions } from '../lib/utils.ts';
|
||||
import { Button } from './ui/Button.tsx';
|
||||
|
||||
const NotConfigured: FC = () => {
|
||||
const NotConfigured: FC<{ open: boolean }> = ({ open }) => {
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-[350px] h-full overflow-y-hidden items-center gap-10 py-10">
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="fixed top-0 bottom-0 left-0 right-0 inset-0 bg-white z-10">
|
||||
<div className="container flex flex-col gap-3 justify-center items-center h-full max-w-lg mx-auto">
|
||||
<img
|
||||
src="./128.png"
|
||||
height="40px"
|
||||
@@ -13,13 +15,23 @@ const NotConfigured: FC = () => {
|
||||
className="rounded"
|
||||
alt="Linkwarden Logo"
|
||||
/>
|
||||
<h1 className="font-medium" style={{ fontSize: '1.65rem' }}>
|
||||
<h1
|
||||
className="font-medium text-lg text-zinc-700"
|
||||
style={{ fontSize: '1.65rem' }}
|
||||
>
|
||||
Initial Setup
|
||||
</h1>
|
||||
|
||||
<div className="flex justify-center items-center">
|
||||
<Button
|
||||
onClick={() => openOptions()}
|
||||
className="w-40"
|
||||
variant="outline"
|
||||
>
|
||||
Configure
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Button onClick={() => openOptions()} className="w-37.5">
|
||||
Configure
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+32
-29
@@ -1,6 +1,9 @@
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { getLinksFetch, checkLinkExists } from './actions/links.ts';
|
||||
import {
|
||||
getLinksFetch,
|
||||
// checkLinkExists
|
||||
} from './actions/links.ts';
|
||||
import { getConfig } from './config.ts';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
@@ -44,12 +47,12 @@ export async function getStorageItem(key: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export const getCurrentLinkItem = async () => {
|
||||
export const checkDuplicatedItem = async () => {
|
||||
const config = await getConfig();
|
||||
const currentTab = await getCurrentTabInfo();
|
||||
const { response } = await getLinksFetch(config.baseUrl, config.apiKey);
|
||||
const itemInfo = response.find((link) => link.url === currentTab.url);
|
||||
return itemInfo || false;
|
||||
const formatLinks = response.map((link) => link.url);
|
||||
return formatLinks.includes(currentTab.url ?? '');
|
||||
};
|
||||
|
||||
export async function setStorageItem(key: string, value: string) {
|
||||
@@ -68,29 +71,29 @@ export function openOptions() {
|
||||
export async function updateBadge(tabId: number | undefined) {
|
||||
if (!tabId) return;
|
||||
|
||||
const browser = getBrowser();
|
||||
|
||||
const cachedConfig = await getConfig();
|
||||
const linkExists = await checkLinkExists(
|
||||
cachedConfig.baseUrl,
|
||||
cachedConfig.apiKey
|
||||
);
|
||||
if (linkExists) {
|
||||
if (browser.action) {
|
||||
browser.action.setBadgeText({ tabId, text: '✓' });
|
||||
browser.action.setBadgeBackgroundColor({ tabId, color: '#98c0ff' });
|
||||
} else {
|
||||
browser.browserAction.setBadgeText({ tabId, text: '✓' });
|
||||
browser.browserAction.setBadgeBackgroundColor({
|
||||
tabId,
|
||||
color: '#98c0ff',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (browser.action) {
|
||||
browser.action.setBadgeText({ tabId, text: '' });
|
||||
} else {
|
||||
browser.browserAction.setBadgeText({ tabId, text: '' });
|
||||
}
|
||||
}
|
||||
// TODO: add url check endpoint for precise matching (instead of fuzzy search)
|
||||
// const browser = getBrowser();
|
||||
// const cachedConfig = await getConfig();
|
||||
// const linkExists = await checkLinkExists(
|
||||
// cachedConfig.baseUrl,
|
||||
// cachedConfig.apiKey
|
||||
// );
|
||||
// if (linkExists) {
|
||||
// if (browser.action) {
|
||||
// browser.action.setBadgeText({ tabId, text: '✓' });
|
||||
// browser.action.setBadgeBackgroundColor({ tabId, color: '#98c0ff' });
|
||||
// } else {
|
||||
// browser.browserAction.setBadgeText({ tabId, text: '✓' });
|
||||
// browser.browserAction.setBadgeBackgroundColor({
|
||||
// tabId,
|
||||
// color: '#98c0ff',
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// if (browser.action) {
|
||||
// browser.action.setBadgeText({ tabId, text: '' });
|
||||
// } else {
|
||||
// browser.browserAction.setBadgeText({ tabId, text: '' });
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
+34
-38
@@ -15,6 +15,7 @@ function App() {
|
||||
(async () => {
|
||||
const cachedOptions = await isConfigured();
|
||||
const cachedConfig = await getConfig();
|
||||
|
||||
setBaseUrl(cachedConfig.baseUrl);
|
||||
setIsAllConfigured(cachedOptions);
|
||||
})();
|
||||
@@ -22,44 +23,39 @@ function App() {
|
||||
|
||||
return (
|
||||
<WholeContainer>
|
||||
{
|
||||
isAllConfigured ? (
|
||||
<Container>
|
||||
<div className="flex justify-between w-full items-center">
|
||||
<div className="flex space-x-2 w-full items-center">
|
||||
<a
|
||||
href={baseUrl}
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
referrerPolicy="no-referrer"
|
||||
className="hover:opacity-80 duration-200 rounded ease-in-out"
|
||||
>
|
||||
<img
|
||||
src="./128.png"
|
||||
height="30px"
|
||||
width="30px"
|
||||
className="rounded"
|
||||
alt="Linkwarden Logo"
|
||||
/>
|
||||
</a>
|
||||
<h1 className="text-lg">Add Link</h1>
|
||||
</div>
|
||||
<div className="flex items-center justify-center space-x-2">
|
||||
<ModeToggle />
|
||||
<p
|
||||
className="text-blue-500 text-xs cursor-pointer hover:opacity-80 duration-200 ease-in-out w-fit"
|
||||
onClick={openOptions}
|
||||
>
|
||||
Config
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<BookmarkForm />
|
||||
</Container>
|
||||
) : (
|
||||
<NotConfigured />
|
||||
)
|
||||
}
|
||||
<Container>
|
||||
<div className="flex justify-between w-full items-center">
|
||||
<div className="flex space-x-2 w-full items-center">
|
||||
<a
|
||||
href={baseUrl}
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
referrerPolicy="no-referrer"
|
||||
className="hover:opacity-80 duration-200 rounded ease-in-out"
|
||||
>
|
||||
<img
|
||||
src="./128.png"
|
||||
height="30px"
|
||||
width="30px"
|
||||
className="rounded"
|
||||
alt="Linkwarden Logo"
|
||||
/>
|
||||
</a>
|
||||
<h1 className="text-lg">Add Link</h1>
|
||||
</div>
|
||||
<div className="flex items-center justify-center space-x-2">
|
||||
<ModeToggle />
|
||||
<p
|
||||
className="text-blue-500 text-xs cursor-pointer hover:opacity-80 duration-200 ease-in-out w-fit"
|
||||
onClick={openOptions}
|
||||
>
|
||||
Config
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<BookmarkForm />
|
||||
<NotConfigured open={!isAllConfigured} />
|
||||
</Container>
|
||||
</WholeContainer>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user