diff --git a/CHANGELOG.MD b/CHANGELOG.MD index f2c1ef2..2d165d6 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,12 @@ # Change Log +## [Version 1.0.5] + +- added: `setting` to enable right click page context like at user suggestion +- added: `setting` to enable chrome notification on like success/fail from right click context +- refactor: track for reward notification +- disabled: some logs + ## [Version 1.0.4] - fix: add missing key diff --git a/manifest.json b/manifest.json index 111f771..510c26d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "yup live", "description": "Light alternative extension for yup protocol", - "version": "1.0.4", + "version": "1.0.5", "manifest_version": 3, "icons": { "16": "src/assets/icons/yup_ext_16.png", @@ -53,6 +53,7 @@ "notifications", "tabs", "clipboardWrite", - "alarms" + "alarms", + "contextMenus" ] } diff --git a/src/background/index.ts b/src/background/index.ts index e759c2a..0c32453 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -1,4 +1,4 @@ -import { SEND_AUTH_NOTIF } from '@/constants/messeges'; +import { SEND_AUTH_NOTIF, ENABLE_RIGHT_CLICK, DISABLE_RIGHT_CLICK } from '@/constants/messeges'; import { initStorage } from '@/utils/storage' import { getStore, setProfile, setNotifStorageNotifs, setSettings, setNotifStorageLastRewardNotif, getNotifStorageLastRewardNotif } from '@/utils/storage' import type { Notification } from '@/utils/types'; @@ -7,11 +7,65 @@ import { getNotifications } from '@/utils/notifications'; import { setBadge } from '@/utils/chrome-misc' import { closeTo } from '@/utils/time'; import { getActionUsage } from '@/utils/user'; +import { executeVote, getVotePayload } from '@/utils/votes'; + // Disable conflict with yup extension const yupExtensionId = 'nhmeoaahigiljjdkoagafdccikgojjoi' console.info('Service worker started') + +const onRightClickLike = async (store, info, tab) => { + const vote = await executeVote(getVotePayload({ + store, + url: tab.url, + type: true + })) + if (store?.settings?.enableRightClickNotif) { + if (vote?._id) { + await chrome.notifications.create({ + type: 'basic', + iconUrl: chrome.runtime.getURL('src/assets/icons/yup_ext_128.png'), + title: 'Yup Live Extension', + message: `Your rating has been submitted`, + }) + } else { + await chrome.notifications.create({ + type: 'basic', + iconUrl: chrome.runtime.getURL('src/assets/icons/yup_ext_128.png'), + title: 'Yup Live Extension', + message: `There was an error submitting your rating`, + }) + } + } +} + +const enableRightClickVote = async () => { + try { + await chrome.contextMenus.create({ + id: "yup-like", + title: "Like this page", + contexts: ["page", "page_action"], + }); + } catch (error) { + // ignore + } + if(chrome.runtime.lastError) { + console.warn('Error creating context menu', chrome.runtime.lastError.message) + } +} + +const disableRightClickVote = async () => { + try { + await chrome.contextMenus.remove("yup-like"); + } catch (error) { + // ignore + } + if(chrome.runtime.lastError) { + console.warn('Error creating context menu', chrome.runtime.lastError.message) + } +} + const alarmHandler = async () => { const store = await getStore() const requests = {} as Record> @@ -67,17 +121,17 @@ const alarmHandler = async () => { if (rewardNotif) { const storeReward = (await getNotifStorageLastRewardNotif()) - if (!storeReward || (storeReward.id !== rewardNotif._id + if (!storeReward || (storeReward.id !== rewardNotif._id && !closeTo(new Date(storeReward.createdAt), new Date(rewardNotif.createdAt), 2e4) - )) { + )) { { - await setNotifStorageLastRewardNotif({ createdAt: rewardNotif.createdAt, id: rewardNotif._id }); - await chrome.notifications.create({ - type: 'basic', - iconUrl: chrome.runtime.getURL('src/assets/icons/yup_ext_128.png'), - title: 'Yup Live Extension', - message: `You have been alocated a future reward of ${rewardNotif.quantity} YUP`, - }) + await setNotifStorageLastRewardNotif({ createdAt: rewardNotif.createdAt, id: rewardNotif._id }); + await chrome.notifications.create({ + type: 'basic', + iconUrl: chrome.runtime.getURL('src/assets/icons/yup_ext_128.png'), + title: 'Yup Live Extension', + message: `You have been alocated a future reward of ${rewardNotif.quantity} YUP`, + }) } } } @@ -86,9 +140,10 @@ const alarmHandler = async () => { if (store.settings?.chromeNotifWhenAbleToVote) { await getActionUsage(store?.user?.auth?.userId) } - + } catch (error) { - console.error('Error fetching notifications', error) + // console.error('Error fetching notifications', error) + // ignore } } @@ -104,19 +159,36 @@ chrome.alarms.create( chrome.alarms.onAlarm.addListener(alarmHandler) -chrome.runtime.onInstalled.addListener(() => { +chrome.runtime.onInstalled.addListener(async () => { initStorage() chrome.management.setEnabled(yupExtensionId, false) + const store = await getStore() + if (store?.user?.auth?.authToken && store?.settings?.enableRightClick) { + enableRightClickVote() + } }); -chrome.runtime.onStartup.addListener(() => { +chrome.runtime.onStartup.addListener(async () => { initStorage() chrome.management.setEnabled(yupExtensionId, false) + const store = await getStore() + if (store?.user?.auth?.authToken && store?.settings?.enableRightClick) { + enableRightClickVote() + } }) - +chrome.contextMenus.onClicked.addListener(async (info, tab) => { + if (info.menuItemId === 'yup-like') { + const store = await getStore() + if (store?.user?.auth?.authToken) { + onRightClickLike(store, info, tab) + } + } +}) + chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { try { + console.log('Message received', request) if (request.type === SEND_AUTH_NOTIF) { chrome.notifications.create({ type: 'basic', @@ -124,11 +196,17 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { title: 'Yup Live Extension', message: 'You have been logged in.', }) + sendResponse({ success: true }) + } else if (request.type === ENABLE_RIGHT_CLICK) { + await enableRightClickVote() + sendResponse({ success: true }) + } else if (request.type === DISABLE_RIGHT_CLICK) { + await disableRightClickVote() + sendResponse({ success: true }) } } catch (error) { console.error('Error in message listener', error) sendResponse({ error }) } - return true }) diff --git a/src/client/content.ts b/src/client/content.ts index 1631285..60cead0 100644 --- a/src/client/content.ts +++ b/src/client/content.ts @@ -22,13 +22,13 @@ if (event.source != window) return; if(allowedEvents.includes(event?.data?.type ?? '')){ - console.log('Yup Live Extension received message:', event.data); + // console.log('Yup Live Extension received message:', event.data); switch (event.data.type) { case SEND_VOTE: - console.log('SEND_VOTE', event.data.payload) + // console.log('SEND_VOTE', event.data.payload) break; case SET_AUTH: - console.log('SET_AUTH', event.data.payload) + // console.log('SET_AUTH', event.data.payload) setAuth(event.data.payload).catch(console.error) break; default: diff --git a/src/constants/messeges.ts b/src/constants/messeges.ts index 6b32e5f..479cd78 100644 --- a/src/constants/messeges.ts +++ b/src/constants/messeges.ts @@ -1,3 +1,5 @@ export const SEND_VOTE = 'SEND_VOTE' export const SET_AUTH = 'SET_AUTH' -export const SEND_AUTH_NOTIF = 'SEND_AUTH_NOTIF' \ No newline at end of file +export const SEND_AUTH_NOTIF = 'SEND_AUTH_NOTIF' +export const ENABLE_RIGHT_CLICK = 'ENABLE_RIGHT_CLICK' +export const DISABLE_RIGHT_CLICK = 'DISABLE_RIGHT_CLICK' \ No newline at end of file diff --git a/src/overlay/Overlay.svelte b/src/overlay/Overlay.svelte index f35a662..5280b80 100644 --- a/src/overlay/Overlay.svelte +++ b/src/overlay/Overlay.svelte @@ -2,7 +2,7 @@ import Alert from "@/components/Alert.svelte"; import '@/overlay/overlay.scss' import { getStore } from "@/utils/storage"; - import { executeVote } from "@/utils/votes"; + import { executeVote, getVotePayload } from "@/utils/votes"; let alert let loading = false @@ -11,18 +11,13 @@ if(loading) return loading = true const store = await getStore() - const payload ={ - userVote: { - like: type, - rating: 1 - }, - post: '', - url: document.location.href.replace(/\/$/gms, ''), - $mainStore: store, - $alertStore: null - } - const vote = await executeVote(payload) - console.log(vote) + + const vote = await executeVote(getVotePayload({ + store, + url: document.location.href, + type + })) + if (vote?._id){ alert.show(type ? 'Liked' : 'Disliked', 'success') } else { diff --git a/src/pages/Settings.svelte b/src/pages/Settings.svelte index eec3194..6b6e048 100644 --- a/src/pages/Settings.svelte +++ b/src/pages/Settings.svelte @@ -7,7 +7,8 @@ import { navigate } from "@/utils/router"; import { storageDefault } from '@/utils/storage' import { onMount } from "svelte"; import PageLoader from "@/components/PageLoader.svelte"; -import { clearBadge, reloadExtension } from '@/utils/chrome-misc'; +import { clearBadge, reloadExtension, sendSWMessage } from '@/utils/chrome-misc'; +import { DISABLE_RIGHT_CLICK, ENABLE_RIGHT_CLICK } from '@/constants/messeges' let settings: typeof $mainStore['settings'] = null; let settingLoading = false; @@ -29,6 +30,16 @@ const setSettingsLocal = async (setting: string, value = '') => { } settings = $mainStore.settings; await setSettings($mainStore.settings); + switch(setting) { + case 'enableRightClick': + if($mainStore.settings[setting]) { + await sendSWMessage({type: ENABLE_RIGHT_CLICK }) + break; + } + await sendSWMessage({type: DISABLE_RIGHT_CLICK }) + break; + } + settingLoading = false; }; @@ -107,6 +118,26 @@ onMount(async () => { +
+ Enable Right Click rating on page + +
+ +
+ Browser notification if right click rating succeeded + +
+ {:else} diff --git a/src/utils/chrome-misc.ts b/src/utils/chrome-misc.ts index 3d15554..c697a69 100644 --- a/src/utils/chrome-misc.ts +++ b/src/utils/chrome-misc.ts @@ -34,4 +34,12 @@ export const getExtensionVersion = () => { export const reloadExtension = () => { chrome.runtime.reload() +} + +export const sendSWMessage = (message: {type: string, [key: string]: any}) => { + return new Promise((resolve) => { + chrome.runtime.sendMessage(message, (response) => { + resolve(response) + }) + }) } \ No newline at end of file diff --git a/src/utils/storage.ts b/src/utils/storage.ts index 7e9e111..9de3bc4 100644 --- a/src/utils/storage.ts +++ b/src/utils/storage.ts @@ -47,6 +47,8 @@ export const storageDefault = { coinGeckoPrice: 0, hasNewNotifications: false, refilNotifTimestamp: 0, + enableRightClick: false, + enableRightClickNotif: false, } } diff --git a/src/utils/votes.ts b/src/utils/votes.ts index 410a47b..f861c1a 100644 --- a/src/utils/votes.ts +++ b/src/utils/votes.ts @@ -1,5 +1,6 @@ import type { Vote } from './types' import { fetchWAuth } from './auth' +import type { StorageType } from './storage' const API_BASE = 'https://api.yup.io' @@ -81,4 +82,23 @@ export const executeVote = async ({ } return null } - } \ No newline at end of file + } + + export const getVotePayload = ({ + url, store, type + }: { + url: string, + store: StorageType, + type: boolean + }) => { + return { + userVote: { + like: type, + rating: 1 + }, + post: '', + url: (url || '').replace(/\/$/gms, ''), + $mainStore: store, + $alertStore: null + } +} \ No newline at end of file