Skip to content

Commit

Permalink
Open guide page on first install close #5
Browse files Browse the repository at this point in the history
  • Loading branch information
TetraTsunami committed May 28, 2024
1 parent d1572b1 commit 8751550
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 1 deletion.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "link-looker",
"displayName": "LinkLooker",
"version": "1.0.0",
"version": "1.1.0",
"description": "Previews links using ChatGPT when you hover over them",
"author": "Tsuni <[email protected]>",
"scripts": {
Expand Down
18 changes: 18 additions & 0 deletions src/background/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const onInstalled = (object) => {
let internalUrl = chrome.runtime.getURL("tabs/getting-started.html");

if (object.reason === chrome.runtime.OnInstalledReason.INSTALL) {
chrome.tabs.create({ url: internalUrl });
}
}
const onClicked = () => {
chrome.tabs.create({ url: chrome.runtime.getURL("tabs/getting-started.html") });
}

chrome.runtime.onInstalled.addListener(onInstalled);

if (chrome.action != undefined) {
chrome.action.onClicked.addListener(onClicked);
} else {
chrome.browserAction.onClicked.addListener(onClicked);
}
1 change: 1 addition & 0 deletions src/contents/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ const SummaryPopup = () => {
await getOAIData(tagData)
} catch (e) {
console.warn("Error getting OpenAI completion: ", e)
setSummary("Error getting summary: " + e)
}
} catch (e) {
console.error(e)
Expand Down
117 changes: 117 additions & 0 deletions src/tabs/getting-started.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { useEffect, useState } from "react"
import "./styles.css"
import icon from "data-base64:/assets/icon.png"
import { useStorage } from "@plasmohq/storage/hook"

import SummaryPopup from "../contents/index"

function FakePopup() {
const [animationState, setAnimationState] = useState("opening")
useEffect(() => {
setTimeout(() => setAnimationState("open"), 800)
})
return (
<div className="hover-popup mx-auto min-h-8 w-[600px] overflow-hidden rounded-xl bg-gray-800/60 text-base text-white shadow-i-sm backdrop-blur-md">
{animationState == "opening" && <div className="loader" />}
{animationState == "open" && (
<div className="inner-popup flex flex-col" style={{"--maxHeight": "500px"} as React.CSSProperties}>
<img className="image-contain" src={icon} />
<div className="flex flex-col gap-2 px-4 pb-4 pt-2">
<h1 className="mb-4 text-4xl font-bold">Welcome to LinkLooker!</h1>
<p>
LinkLooker is a browser extension that helps you preview links before you click on them. Hover over almost any link to see a preview of the content behind it!
</p>
<div className="summary relative flex flex-col gap-2 italic">
<p>
If you configure an OpenAI API key, you can also get an AI-generated summary of the content!
</p>
</div>
</div>
<div className="w-full bg-gray-700/50 p-4 pt-3">
<p className="text-sm text-gray-400">Brought to you by <a href="https://tsuni.dev">Tsuni</a></p>
</div>
</div>
)}
</div>
)
}

function BaseOptions() {
const [apiKey, setApiKey] = useStorage("openai-key", "")

return (<fieldset>
<legend>Options</legend>
<div className="options-grid">
<label htmlFor="key">OpenAI API Key</label>
<input
type="password"
id="key"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)} />
</div>
<p className="italic">The model recieves the text of the hovered link and the beginning of the content text.</p>
</fieldset>)
}

const APIGuide = () => (
<details className="w-full overflow-hidden">
<summary className="text-xl font-semibold">How Do I Get An API Key??</summary>
<ol className="flex list-decimal flex-col items-start gap-3 ps-[40px]">
<li>Go to <a className="text-blue-400 underline" href="https://platform.openai.com/signup">OpenAI's website</a> and sign up for an account.</li>
<img className="rounded-xl shadow-i-sm" src="https://cloud.tsuni.dev/f/fa86976461b14a71aaaf/?dl=1" alt="OpenAI API key creation modal with red markers indicating steps to access it" />
<li>Once you're logged in, go to the <a className="text-blue-400 underline" href="https://platform.openai.com/account/api-keys">API keys page</a>.</li>
<li>Click the "Create New Secret Key" button.</li>
<li>Give your key a name and click "Create".</li>
<li>Copy the key and paste it into the input above.</li>
</ol>
</details>
)


function GettingStartedPage() {
const [animationState, setAnimationState] = useState("opening")
useEffect(() => {
setTimeout(() => setAnimationState("open"), 1600)
})
return (
<main
className="min-h-screen bg-neutral-800 text-lg text-white">
<SummaryPopup />
<div className="container mx-auto flex flex-col items-center gap-12 p-4">
<div className="h-[340px]">
<FakePopup />
</div>
{animationState == "open" && <div className="inner-popup flex flex-col items-center gap-16"
style={{"--maxHeight": "10000px"} as React.CSSProperties}>
<section className="flex flex-col items-center gap-4">
<h1 className="text-4xl font-semibold">First Things First...</h1>
<p>This extension works much better once it's configured.</p>
<BaseOptions />
<APIGuide />
</section>
<section className="flex max-w-prose flex-col items-center gap-4">
<h1 className="text-4xl font-semibold">How Does It Work?</h1>
<p>Most websites already provide titles, cover images, and descriptions for their pages. Usually, you only see them when you post a link on social media, like Discord or Twitter. This extension uses that information to create a popup when you hover over a link. If you add an OpenAI API key, this extension also extracts some of the article text on the page, and sends that to OpenAI for further summary. You can always tell the difference between the description provided by the page and the AI's description by the different styles of text in the popup.</p>
</section>
<section className="flex max-w-prose flex-col items-center gap-4">
<h1 className="text-4xl font-semibold">Try It Out!</h1>
<p>Here are some pages to try out the extension on (you can use it here, or open the pages yourself):</p>
<p>Hover over the links with your mouse, and press the SHIFT key on your keyboard.</p>
<ul className="flex list-disc flex-col gap-2">
<li><a className="text-blue-400 underline hover:animate-pulse" href="https://www.theverge.com/2019/5/21/18634195/t-mobile-sprint-merger-conditions-access-coverage">An article with lots of links</a></li>
<li><a className="text-blue-400 underline hover:animate-pulse" href="https://www.visitmadison.com/things-to-do/attractions/">Things to do in Madison, WI</a></li>
<li><a className="text-blue-400 underline hover:animate-pulse" href="https://en.wikipedia.org/wiki/Tetra">A wikipedia page</a></li>
</ul>
</section>
<section className="flex max-w-prose flex-col items-center gap-4">
<h1 className="text-4xl font-semibold">Need Help?</h1>
<p>This extension doesn't work on PDFs, pages with URL anchors, or while you're on Wikipedia (they already have popups). Also, there are a lot more options available in the <a className="cursor-pointer text-blue-400 underline" onClick={() => chrome.runtime.openOptionsPage()}>settings</a> page of this extension.</p>
<p>If you have any questions or need help, feel free to open an issue on <a className="text-blue-400 underline" href="https://github.com/TetraTsunami/linklooker/issues">Github</a>!</p>
</section>
</div>}
</div>
</main>
)
}

export default GettingStartedPage
150 changes: 150 additions & 0 deletions src/tabs/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

main {
padding: 1rem;
}

fieldset {
display: flex;
flex-direction: column;
gap: 0.5rem;
border-radius: 5px;
border: 1px solid white;
margin-bottom: 10px;
padding: 0.5rem 1rem;
}

fieldset legend{
font-weight: bolder;
font-size: large;
margin-left: 1rem;
}

.options-grid {
display: grid;
grid-template-columns: auto minmax(50px, 1fr);
gap: 10px;
}

input, textarea {
color: black;
padding: 2px;
}

textarea {
resize: vertical;
height: 5em;
}

.hover-popup {
animation: growDown 0.6s ease-in-out forwards;
}

.hide {
animation: shrinkDown 0.1s ease-in forwards;
}

.summary {
margin-left: 12px;
}

.summary::before {
content: " ";
position: absolute;
top: 0;
bottom: 0;
left: -8px;
background: rgba(232, 166, 250, 0.50);
width: 2px;
border-radius: 2px;
}

.word {
animation: fadeUp 0.5s ease-out;
}

.inner-popup {
animation: growToFit 1s ease-out forwards;
}

@keyframes fadeUp {
0% {
transform: translateY(5px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}

@keyframes growDown {
0% {
transform: translateY(-10px);
max-height: 0;
opacity: 0;
}
100% {
transform: translateY(0);
max-height: 700px;
opacity: 1;
}
}

@keyframes shrinkDown {
0% {
transform: translateY(0);
max-height: 700px;
opacity: 1;
}
100% {
transform: translateY(-10px);
max-height: 0;
opacity: 0;
}
}

@keyframes growToFit {
0% {
max-height: 0;
opacity: 0;
}
100% {
max-height: var(--maxHeight);
opacity: 1;
}
}

.image-contain { /* Used for logos, left align */
max-height: 100px;
padding: 0.5rem;
object-fit: contain;
align-self: start;
}

.image-cover { /* Used for backgrounds that we can cut off */
max-height: 200px;
width: 100%;
object-fit: cover;
}

/* https://css-loaders.com/spinner/ */
.loader {
width: 30px;
margin: 10px auto;
padding: 6px;
aspect-ratio: 1;
border-radius: 50%;
background: #eeed;
--_m:
conic-gradient(#0000 10%,#000),
linear-gradient(#000 0 0) content-box;
-webkit-mask: var(--_m);
mask: var(--_m);
-webkit-mask-composite: source-out;
mask-composite: subtract;
animation: l3 1.5s infinite linear;
}
@keyframes l3 {to{transform: rotate(1turn)}}
1 change: 1 addition & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = {
extend: {
boxShadow: {
"i-lg": "#000b 0px 10px 40px, #fff5 0px 0px 20px inset",
"i-sm": "#0008 0px 5px 20px, #fff5 0px 0px 10px inset",
}
}
}
Expand Down

0 comments on commit 8751550

Please sign in to comment.