Skip to content

Commit

Permalink
Feature: Added a service worker that listens to a dynamic ContextMenu…
Browse files Browse the repository at this point in the history
…s for quickly enabling recent experiments
  • Loading branch information
aaron5670 committed Mar 15, 2023
1 parent c254c03 commit 25ae974
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 50 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "toggle-experiment",
"displayName": "Toggle Experiment",
"description": "A browser extension to inject the LocalStorage of a website for Optimizely experiments.",
"version": "0.7.0",
"version": "0.8.0",
"author": "Aaron van den Berg",
"homepage": "https://aaronvandenberg.nl/",
"scripts": {
Expand Down
47 changes: 47 additions & 0 deletions src/background.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { setLocalStorageValue } from "~local-storage-injector";

const broadcastChannel = new BroadcastChannel('broadcastChannel');

broadcastChannel.onmessage = (event) => {
const { data } = event;
const { history, localStorageKey } = data;

// set the localStorageKey to the one that was sent from the content script
if (localStorageKey) {
chrome.storage.local.set({
"localStorageKey": localStorageKey,
}, function () {
console.log(`localStorageKey is set to '${localStorageKey}'`);
});
}

if(history?.length > 1) {
// first remove all the context menus
chrome.contextMenus.removeAll();

// then create the new ones
history.forEach((item) => {
chrome.contextMenus.create({
id: item.key,
title: `${item.name} (${item.key})`,
type: "normal",
contexts: ["all"],
});
})
} else {
chrome.contextMenus.removeAll();
}
}

chrome.contextMenus.onClicked.addListener(async (info, tabs) => {
chrome.storage.local.get(['localStorageKey'], async function(result) {
await chrome.scripting.executeScript(
{
target: { tabId: tabs.id },
world: "MAIN", // MAIN in order to access the window object
func: setLocalStorageValue,
args: [result.localStorageKey, info.menuItemId]
}
)
});
});
13 changes: 4 additions & 9 deletions src/components/HistoryItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,19 @@ interface HistoryItemsProps {
export function HistoryItems({ links, active }: HistoryItemsProps) {
const { classes, cx } = useStyles();
const { localStorageKey, setLocalStorageValue } = useStore(state => state);

const saveToLocalStorage = (value) => {
setLocalStorageValue(value);

chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
updateLocalStorageValue(tabs[0].id, localStorageKey, value);
});
};

const setHistoryValue = (e, itemKey) => {
e.preventDefault();
saveToLocalStorage(itemKey);
}

const items = links.map((item) => (
<Box<'a'>
component="a"
onClick={(event) => setHistoryValue(event, item.key)}
onClick={() => saveToLocalStorage(item.key)}
key={item.key}
className={cx(classes.link, { [classes.linkActive]: active === item.key })}
>
Expand All @@ -72,4 +67,4 @@ export function HistoryItems({ links, active }: HistoryItemsProps) {
{items}
</>
);
}
}
23 changes: 15 additions & 8 deletions src/components/SearchItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { IconPlayerPlay, IconPlayerPause, IconPencil, IconQuestionMark, IconExte
import useStore from "~store/useStore";
import { updateLocalStorageValue } from "~handlers/localStorageHandlers";
import { Storage } from "@plasmohq/storage";
import type { HistoryItems } from '~types/types';
import type { HistoryItems } from "~types/types";

const broadcastChannel = new BroadcastChannel("broadcastChannel");

const useStyles = createStyles((theme) => ({
card: {
Expand All @@ -29,7 +31,7 @@ interface SearchItemProps {
};
}

const storage = new Storage()
const storage = new Storage();

const SearchItem = ({ experiment }: SearchItemProps) => {
const { classes } = useStyles();
Expand Down Expand Up @@ -66,23 +68,26 @@ const SearchItem = ({ experiment }: SearchItemProps) => {
const addHistoryItem = async (newItem: HistoryItems) => {
const maxHistoryItems = 3;
const historyItemsLocalStorage = await storage.get("history");
const newHistoryItems = historyItemsLocalStorage ? JSON.parse(historyItemsLocalStorage) : []
const newHistoryItems = historyItemsLocalStorage ? JSON.parse(historyItemsLocalStorage) : [];

if(newHistoryItems.find((item: { key: string; }) => item.key === newItem.key)) {
if (newHistoryItems.find((item: { key: string; }) => item.key === newItem.key)) {
return;
}

if(newHistoryItems.length === maxHistoryItems) {
if (newHistoryItems.length >= maxHistoryItems) {
newHistoryItems.shift();
}

newHistoryItems.push(newItem);
setHistoryItems(newHistoryItems);
}

// Broadcast history to service worker
broadcastChannel.postMessage({ history: newHistoryItems });
};

const saveToLocalStorage = (value, experimentName) => {
setLocalStorageValue(value);
addHistoryItem({name: experimentName, key: value});
addHistoryItem({ name: experimentName, key: value });

chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
updateLocalStorageValue(tabs[0].id, localStorageKey, value);
Expand Down Expand Up @@ -141,7 +146,9 @@ const SearchItem = ({ experiment }: SearchItemProps) => {
</Text>
</Group>
<Text>
<Anchor href={`https://app.optimizely.com/v2/projects/${experiment.project_id}/experiments/${experiment.id}`} target="_blank">
<Anchor
href={`https://app.optimizely.com/v2/projects/${experiment.project_id}/experiments/${experiment.id}`}
target="_blank">
<IconExternalLink size={18} stroke={1.5} style={{ marginBottom: -4 }} /> Optimizely
</Anchor>
</Text>
Expand Down
16 changes: 14 additions & 2 deletions src/components/settings/LocalStorageInputField.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
import { TextInput } from "@mantine/core";
import useStore from "~store/useStore";

const broadcastChannel = new BroadcastChannel("broadcastChannel");

const LocalStorageField = () => {
const { localStorageKey, setLocalStorageKey } = useStore(state => state);
const { localStorageKey, setLocalStorageKey, historyItems } = useStore(state => state);

const handleChange = (value) => {
setLocalStorageKey(value)

// Broadcast localStorageKey to service worker
broadcastChannel.postMessage({
history: historyItems,
localStorageKey: value,
});
}

return (
<TextInput
label="LocalStorage key"
description="Default value: optimizelyNonLoggedInUser"
value={localStorageKey}
onChange={(e) => setLocalStorageKey(e.target.value)}
onChange={(e) => handleChange(e.target.value)}
mb="lg"
/>
);
Expand Down
33 changes: 25 additions & 8 deletions src/popup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,53 @@
import { useEffect } from "react";
import { Storage } from "@plasmohq/storage"
import { Storage } from "@plasmohq/storage";
import useStore from "~store/useStore";
import HomeScreen from "~screens/Home";
import History from "~screens/History"
import History from "~screens/History";
import Settings from "~screens/Settings";
import Search from "~screens/Search";
import type { Screen } from "~types/types";
import ConnectOptimizely from "~screens/ConnectOptimizely";

const storage = new Storage()
const storage = new Storage();
const broadcastChannel = new BroadcastChannel("broadcastChannel");

function IndexPopup() {
const {setLocalStorageValue, screen, setLocalStorageKey, setOptimizelyAccessToken, setOptimizelyProjectId, setScreen} = useStore(state => state);
const {
setLocalStorageValue,
screen,
setLocalStorageKey,
setOptimizelyAccessToken,
setOptimizelyProjectId,
setScreen,
setHistoryItems
} = useStore(state => state);

useEffect(() => {
const load = async () => {
const setInitialData = async () => {
const key = await storage.get("localStorageKey");
const value = await storage.get("localStorageValue");
const defaultScreen = await storage.get<Screen | null>("defaultScreen");
const optimizelyAccessToken = await storage.get("optimizelyAccessToken");
const optimizelyProjectId = await storage.get("optimizelyProjectId");
const history = await storage.get("history");
setLocalStorageKey(key ?? "optimizelyNonLoggedInUser");
setLocalStorageValue(value ?? "");
setOptimizelyAccessToken(optimizelyAccessToken ?? "");
setOptimizelyProjectId(optimizelyProjectId ?? null);
setScreen(defaultScreen ?? "home");
}
load();
setHistoryItems(history ? JSON.parse(history) : []);

// Broadcast history and localStorageKey to service worker
broadcastChannel.postMessage({
history: history ? JSON.parse(history) : null,
localStorageKey: key ?? "optimizelyNonLoggedInUser",
});
};
setInitialData();
}, []);

return (
<div style={{width: 350}}>
<div style={{ width: 350 }}>
{screen === "home" && <HomeScreen />}
{screen === "history" && <History />}
{screen === "settings" && <Settings />}
Expand Down
28 changes: 6 additions & 22 deletions src/screens/History.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
import { useEffect, useState } from "react";
import Header from "~components/Header";
import { Anchor, Card, Center, Button, Container } from "@mantine/core";
import { Card, Center, Button, Container } from "@mantine/core";
import { IconTrash } from "@tabler/icons-react";
import { Storage } from "@plasmohq/storage";
import useStore from "~store/useStore";

import { HistoryItems } from "~components/HistoryItems";

const storage = new Storage();
const broadcastChannel = new BroadcastChannel('broadcastChannel');

const History = () => {
const [historyItems, setHistoryItems] = useState([]);
const { localStorageValue } = useStore(state => state);

useEffect(() => {
const load = async () => {
const historyLocalStorage = await storage.get("history");
if (historyLocalStorage) {
const historyItemArray = JSON.parse(historyLocalStorage);
if (historyItemArray?.length > 0) {
setHistoryItems(historyItemArray);
}
}
};
load();
}, []);
const { localStorageValue, historyItems, setHistoryItems } = useStore(state => state);

const clearHistory = async (e) => {
e.preventDefault();
setHistoryItems([]);
await storage.remove("history");

// broadcast to service worker
broadcastChannel.postMessage({ history: null });
};

return (
Expand All @@ -52,11 +41,6 @@ const History = () => {
</Button>
</Center>
</Container>
<Center>
<Anchor href="https://github.com/aaron5670/toggle-experiments-extension" target="_blank" mt="md">
GitHub
</Anchor>
</Center>
</Card>
</>
);
Expand Down

0 comments on commit 25ae974

Please sign in to comment.