···1+import type { Metadata } from 'next';
2+3+export const metadata: Metadata = {
4+ title: 'Semble bookmarklet',
5+ description:
6+ 'Learn how to add our bookmarklet to your browser to quickly open any webpage in Semble.',
7+};
8+9+interface Props {
10+ children: React.ReactNode;
11+}
12+13+export default function Layout(props: Props) {
14+ return props.children;
15+}
+82-55
src/webapp/app/bookmarklet/page.tsx
···9 Code,
10 Alert,
11 Box,
0012 Group,
0013} from '@mantine/core';
14import { useState } from 'react';
15import { BiInfoCircle } from 'react-icons/bi';
001617export default function BookmarkletPage() {
18- const [copied, setCopied] = useState(false);
19-20 const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://127.0.0.1:4000';
2122 const bookmarkletCode = `javascript:(function(){
23 const currentUrl = window.location.href;
24 const sembleUrl = '${appUrl}/url?id=' + currentUrl;
25 window.open(sembleUrl, '_blank');
26- })();`;
27-28- const handleCopy = async () => {
29- try {
30- await navigator.clipboard.writeText(bookmarkletCode);
31- setCopied(true);
32- setTimeout(() => setCopied(false), 2000);
33- } catch (err) {
34- console.error('Failed to copy bookmarklet:', err);
35- }
36- };
3738 // Create the bookmarklet link using dangerouslySetInnerHTML to bypass React's security check
39 const createBookmarkletLink = () => {
40 return {
41- __html: `<a href="${bookmarkletCode}" style="text-decoration: none; padding: 8px 16px; background-color: var(--mantine-color-orange-6); color: white; border-radius: 4px; display: inline-flex; align-items: center; gap: 8px;"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>Open in Semble</a>`,
42 };
43 };
4445 return (
46- <Container size="md" py="xl">
47 <Stack gap="xl">
48- <Stack gap="md">
49- <Title order={1}>Semble Bookmarklet</Title>
50- <Text size="lg" c="dimmed">
51- Add this bookmarklet to your browser to quickly open any webpage in
52- Semble.
53- </Text>
00000000000000000000054 </Stack>
5556- <Alert icon={<BiInfoCircle />} title="How to install" color="orange">
57 <Stack gap="sm">
58- <Text>
59- 1. Copy the bookmarklet code below or drag the button to your
60- bookmarks bar
61- </Text>
62- <Text>
63- {
64- "2. When you're on any webpage, click the bookmarklet to open it in Semble"
65- }
66- </Text>
0000000000067 </Stack>
68 </Alert>
6970 <Stack gap="md">
71- <Title order={2} size="h3">
72- Method 1: Drag to Bookmarks Bar
73- </Title>
74- <Text c="dimmed">
75- {"Drag this button directly to your browser's bookmarks bar:"}
76- </Text>
77 <Group>
78 <Box dangerouslySetInnerHTML={createBookmarkletLink()} />
79 </Group>
80 </Stack>
8182 <Stack gap="md">
83- <Title order={2} size="h3">
84- Method 2: Copy Code
85- </Title>
86- <Text c="dimmed">
87- Copy this code and create a new bookmark with it as the URL:
88- </Text>
89 <Box pos="relative">
90 <Code
91 block
···98 >
99 {bookmarkletCode}
100 </Code>
101- <Button
102- size="xs"
103- variant="light"
104- onClick={handleCopy}
105- style={{
106- position: 'absolute',
107- top: '8px',
108- right: '8px',
109- }}
110- >
111- {copied ? 'Copied!' : 'Copy'}
112- </Button>
0113 </Box>
114 </Stack>
115 </Stack>
···9 Code,
10 Alert,
11 Box,
12+ Badge,
13+ Image,
14 Group,
15+ Anchor,
16+ CopyButton,
17} from '@mantine/core';
18import { useState } from 'react';
19import { BiInfoCircle } from 'react-icons/bi';
20+import SembleLogo from '@/assets/semble-logo.svg';
21+import Link from 'next/link';
2223export default function BookmarkletPage() {
0024 const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://127.0.0.1:4000';
2526 const bookmarkletCode = `javascript:(function(){
27 const currentUrl = window.location.href;
28 const sembleUrl = '${appUrl}/url?id=' + currentUrl;
29 window.open(sembleUrl, '_blank');
30+})();`;
00000000003132 // Create the bookmarklet link using dangerouslySetInnerHTML to bypass React's security check
33 const createBookmarkletLink = () => {
34 return {
35+ __html: `<a href="${bookmarkletCode}" style="text-decoration: none; padding: 8px 16px; background-color: var(--mantine-color-tangerine-6); color: white; border-radius: 100px; display: inline-flex; align-items: center; gap: 8px; font-weight: 600;"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>Open in Semble</a>`,
36 };
37 };
3839 return (
40+ <Container size="sm" p="md">
41 <Stack gap="xl">
42+ <Stack gap="xs" align="center">
43+ <Stack align="center" gap={'xs'}>
44+ <Anchor component={Link} href={'/'}>
45+ <Image
46+ src={SembleLogo.src}
47+ alt="Semble logo"
48+ w={48}
49+ h={64.5}
50+ mx={'auto'}
51+ />
52+ <Badge size="sm">Alpha</Badge>
53+ </Anchor>
54+ </Stack>
55+ <Stack gap={'xs'} align="center">
56+ <Title order={1}>Semble Bookmarklet</Title>
57+ <Title
58+ order={2}
59+ size="xl"
60+ c="dimmed"
61+ fw={600}
62+ maw={500}
63+ ta={'center'}
64+ >
65+ Add this bookmarklet to your browser to quickly open any webpage
66+ in Semble.
67+ </Title>
68+ </Stack>
69 </Stack>
7071+ <Alert title="How to install" color="grape">
72 <Stack gap="sm">
73+ <Group gap={'xs'}>
74+ <Badge size="md" color="grape" circle>
75+ 1
76+ </Badge>
77+ <Text fw={500} c="grape">
78+ Copy the bookmarklet code below or drag the button to your
79+ bookmarks bar
80+ </Text>
81+ </Group>
82+ <Group gap={'xs'}>
83+ <Badge size="md" color="grape" circle>
84+ 2
85+ </Badge>
86+87+ <Text fw={500} c={'grape'}>
88+ {
89+ "When you're on any webpage, click the bookmarklet to open it in Semble"
90+ }
91+ </Text>
92+ </Group>
93 </Stack>
94 </Alert>
9596 <Stack gap="md">
97+ <Stack gap={'xs'}>
98+ <Title order={3}>Method 1: Drag to Bookmarks Bar</Title>
99+ <Text c="dimmed" fw={500}>
100+ {"Drag this button directly to your browser's bookmarks bar:"}
101+ </Text>
102+ </Stack>
103 <Group>
104 <Box dangerouslySetInnerHTML={createBookmarkletLink()} />
105 </Group>
106 </Stack>
107108 <Stack gap="md">
109+ <Stack gap={'xs'}>
110+ <Title order={3}>Method 2: Copy Code</Title>
111+ <Text c="dimmed" fw={500}>
112+ Copy this code and create a new bookmark with it as the URL:
113+ </Text>
114+ </Stack>
115 <Box pos="relative">
116 <Code
117 block
···124 >
125 {bookmarkletCode}
126 </Code>
127+ <CopyButton value={bookmarkletCode}>
128+ {({ copied, copy }) => (
129+ <Button
130+ color="dark"
131+ pos={'absolute'}
132+ top={12}
133+ right={12}
134+ onClick={copy}
135+ >
136+ {copied ? 'Copied!' : 'Copy'}
137+ </Button>
138+ )}
139+ </CopyButton>
140 </Box>
141 </Stack>
142 </Stack>