+15
src/webapp/app/bookmarklet/layout.tsx
+15
src/webapp/app/bookmarklet/layout.tsx
···
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
+82
-55
src/webapp/app/bookmarklet/page.tsx
···
9
9
Code,
10
10
Alert,
11
11
Box,
12
+
Badge,
13
+
Image,
12
14
Group,
15
+
Anchor,
16
+
CopyButton,
13
17
} from '@mantine/core';
14
18
import { useState } from 'react';
15
19
import { BiInfoCircle } from 'react-icons/bi';
20
+
import SembleLogo from '@/assets/semble-logo.svg';
21
+
import Link from 'next/link';
16
22
17
23
export default function BookmarkletPage() {
18
-
const [copied, setCopied] = useState(false);
19
-
20
24
const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://127.0.0.1:4000';
21
25
22
26
const bookmarkletCode = `javascript:(function(){
23
27
const currentUrl = window.location.href;
24
28
const sembleUrl = '${appUrl}/url?id=' + currentUrl;
25
29
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
-
};
30
+
})();`;
37
31
38
32
// Create the bookmarklet link using dangerouslySetInnerHTML to bypass React's security check
39
33
const createBookmarkletLink = () => {
40
34
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>`,
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>`,
42
36
};
43
37
};
44
38
45
39
return (
46
-
<Container size="md" py="xl">
40
+
<Container size="sm" p="md">
47
41
<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>
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>
54
69
</Stack>
55
70
56
-
<Alert icon={<BiInfoCircle />} title="How to install" color="orange">
71
+
<Alert title="How to install" color="grape">
57
72
<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>
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>
67
93
</Stack>
68
94
</Alert>
69
95
70
96
<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>
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>
77
103
<Group>
78
104
<Box dangerouslySetInnerHTML={createBookmarkletLink()} />
79
105
</Group>
80
106
</Stack>
81
107
82
108
<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>
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>
89
115
<Box pos="relative">
90
116
<Code
91
117
block
···
98
124
>
99
125
{bookmarkletCode}
100
126
</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>
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>
113
140
</Box>
114
141
</Stack>
115
142
</Stack>