From 9d376f8cf10630a15645f592837619b05aa085f7 Mon Sep 17 00:00:00 2001 From: rofe Date: Sun, 6 Feb 2022 14:29:27 +0100 Subject: [PATCH 1/2] feat: simplify adding project from share url --- src/extension/background.js | 23 ++++++---- src/extension/installhelper.js | 83 ++++++++++++++++++++++++++++++++++ src/extension/options.js | 20 ++------ src/extension/utils.js | 25 ++++++++-- 4 files changed, 121 insertions(+), 30 deletions(-) create mode 100644 src/extension/installhelper.js diff --git a/src/extension/background.js b/src/extension/background.js index a7ec5d596..ebbdb314a 100644 --- a/src/extension/background.js +++ b/src/extension/background.js @@ -14,9 +14,8 @@ import { GH_URL, - SHARE_URL, + SHARE_PREFIX, DEV_URL, - url, log, i18n, getState, @@ -51,7 +50,7 @@ async function checkContextMenu(tabUrl, configs) { // clear context menu browser.contextMenus.removeAll(); // check if add project is applicable - if (configs && (tabUrl.startsWith(GH_URL) || tabUrl.startsWith(SHARE_URL))) { + if (configs && (tabUrl.startsWith(GH_URL) || new URL(tabUrl).pathname === SHARE_PREFIX)) { const { giturl } = getConfigFromTabUrl(tabUrl); if (giturl) { const { owner, repo } = getGitHubSettings(giturl); @@ -85,6 +84,17 @@ function checkTab(id) { .then(async (tab = {}) => { if (!tab.url) return; checkContextMenu(tab.url, configs); + if (new URL(tab.url).pathname === SHARE_PREFIX) { + log.debug('share url detected, inject install helper'); + try { + // instrument generator page + browser.tabs.executeScript(id, { + file: './installhelper.js', + }); + } catch (e) { + log.error('error instrumenting generator page', id, e); + } + } const matches = getConfigMatches(configs, tab.url, proxyUrl); log.debug('checking', id, tab.url, matches); const allowed = matches.length > 0; @@ -136,12 +146,7 @@ function toggle(id) { addProject: async (tabUrl) => { const cfg = getConfigFromTabUrl(tabUrl); if (cfg.giturl) { - await addConfig(cfg, (added) => { - if (added && tabUrl !== url('options.html')) { - // redirect to options page - window.open(url('options.html')); - } - }); + await addConfig(cfg); } }, }; diff --git a/src/extension/installhelper.js b/src/extension/installhelper.js new file mode 100644 index 000000000..f87f4aa10 --- /dev/null +++ b/src/extension/installhelper.js @@ -0,0 +1,83 @@ +/* + * Copyright 2022 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +'use strict'; + +(async () => { + // ensure hlx namespace + window.hlx = window.hlx || {}; + + const { + log, + getState, + getGitHubSettings, + addConfig, + deleteConfig, + } = await import('./utils.js'); + const run = () => { + getState(({ + configs, + }) => { + const usp = new URLSearchParams(window.location.search); + const project = usp.get('project'); + const giturl = usp.get('giturl'); + if (!giturl) { + log.debug('installhelper.js: no project configured yet, ignoring'); + return; + } + log.debug('installhelper.js: run instrumentation', giturl); + + // find bookmarklet container + const bookmarkletContainer = document.querySelector('#sidekick-generator-bookmarklet'); + if (!bookmarkletContainer) { + log.debug('installhelper.js: expected content not found, ignoring'); + } + + const { owner, repo } = getGitHubSettings(giturl); + const configIndex = configs.findIndex((cfg) => cfg.owner === owner && cfg.repo === repo); + if (configIndex < 0 && owner && repo) { + log.info('installhelper.js: project not added yet'); + const addProjectContainer = document.querySelector('#sidekick-generator-extension-add-project'); + if (addProjectContainer) { + // instrument add project button + const button = addProjectContainer.querySelector('a'); + button.addEventListener('click', () => { + addConfig({ giturl, project }, () => window.location.reload()); + }); + // show add project container, hide bookmarklet container + addProjectContainer.parentElement.classList.remove('hidden'); + bookmarkletContainer.parentElement.classList.add('hidden'); + } + } else { + log.info('installhelper.js: project added'); + const deleteProjectContainer = document.querySelector('#sidekick-generator-extension-delete-project'); + if (deleteProjectContainer) { + // instrument delete project button + const button = deleteProjectContainer.querySelector('a'); + button.addEventListener('click', () => { + deleteConfig(configIndex, () => window.location.reload()); + }); + // show delete project container, hide bookmarklet container + deleteProjectContainer.parentElement.classList.remove('hidden'); + bookmarkletContainer.parentElement.classList.add('hidden'); + } + } + }); + }; + window.hlx = window.hlx || {}; + if (!window.hlx.sidekickGeneratorInstrumented) { + window.addEventListener('sidekickGeneratorReady', () => { + run(); + }); + window.hlx.sidekickGeneratorInstrumented = true; + } +})(); diff --git a/src/extension/options.js b/src/extension/options.js index 07abb8f25..14d88372b 100644 --- a/src/extension/options.js +++ b/src/extension/options.js @@ -21,6 +21,7 @@ import { getShareSettings, i18n, addConfig, + deleteConfig, assembleConfig, } from './utils.js'; @@ -79,11 +80,11 @@ function drawConfigs() { }); // wire edit buttons document.querySelectorAll('button.editConfig').forEach((button, i) => { - button.addEventListener('click', (evt) => editConfig(i, evt)); + button.addEventListener('click', () => editConfig(i)); }); // wire delete buttons document.querySelectorAll('button.deleteConfig').forEach((button, i) => { - button.addEventListener('click', (evt) => deleteConfig(i, evt)); + button.addEventListener('click', () => deleteConfig(i, drawConfigs)); }); }); } @@ -198,21 +199,6 @@ function editConfig(i) { }); } -function deleteConfig(i) { - // eslint-disable-next-line no-alert - if (window.confirm(i18n('config_delete_confirm'))) { - browser.storage.sync - .get('hlxSidekickConfigs') - .then(({ hlxSidekickConfigs = [] }) => { - hlxSidekickConfigs.splice(i, 1); - return hlxSidekickConfigs; - }) - .then((hlxSidekickConfigs) => browser.storage.sync.set({ hlxSidekickConfigs })) - .then(() => drawConfigs()) - .catch((e) => log.error('error deleting config', e)); - } -} - function clearForms() { document.querySelectorAll('input, textarea').forEach((field) => { field.value = ''; diff --git a/src/extension/utils.js b/src/extension/utils.js index d00610ece..9b1d3bf30 100644 --- a/src/extension/utils.js +++ b/src/extension/utils.js @@ -14,7 +14,7 @@ import {} from './lib/polyfills.min.js'; -export const SHARE_URL = 'https://www.hlx.live/tools/sidekick/?'; +export const SHARE_PREFIX = '/tools/sidekick/'; export const GH_URL = 'https://github.com/'; @@ -156,7 +156,7 @@ export function getConfigMatches(configs, tabUrl, proxyUrl) { } export function getShareSettings(shareurl) { - if (typeof shareurl === 'string' && shareurl.startsWith(SHARE_URL)) { + if (typeof shareurl === 'string' && new URL(shareurl).pathname === SHARE_PREFIX) { try { const params = new URL(shareurl).searchParams; const giturl = params.get('giturl'); @@ -227,11 +227,11 @@ export async function assembleConfig({ export async function addConfig(input, cb) { const config = await assembleConfig(input); const { - owner, repo, ref, mountpoints, + owner, repo, mountpoints, } = config; getState(({ configs }) => { /* eslint-disable no-alert */ - if (!configs.find((cfg) => owner === cfg.owner && repo === cfg.repo && ref === cfg.ref)) { + if (!configs.find((cfg) => owner === cfg.owner && repo === cfg.repo)) { configs.push(config); browser.storage.sync .set({ hlxSidekickConfigs: configs }) @@ -251,6 +251,23 @@ export async function addConfig(input, cb) { }); } +export async function deleteConfig(i, cb) { + // eslint-disable-next-line no-alert + if (window.confirm(i18n('config_delete_confirm'))) { + browser.storage.sync + .get('hlxSidekickConfigs') + .then(({ hlxSidekickConfigs = [] }) => { + hlxSidekickConfigs.splice(i, 1); + return hlxSidekickConfigs; + }) + .then((hlxSidekickConfigs) => browser.storage.sync.set({ hlxSidekickConfigs })) + .then(() => { + if (typeof cb === 'function') cb(true); + }) + .catch((e) => log.error('error deleting config', e)); + } +} + export async function setDisplay(display, cb) { browser.storage.local .set({ From d90c25e127930695ba647f45175d705e91238c88 Mon Sep 17 00:00:00 2001 From: rofe Date: Mon, 7 Feb 2022 16:53:09 +0100 Subject: [PATCH 2/2] chore: also run (once) if page already loaded --- src/extension/installhelper.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/extension/installhelper.js b/src/extension/installhelper.js index f87f4aa10..d1bb3167c 100644 --- a/src/extension/installhelper.js +++ b/src/extension/installhelper.js @@ -73,11 +73,15 @@ } }); }; - window.hlx = window.hlx || {}; - if (!window.hlx.sidekickGeneratorInstrumented) { - window.addEventListener('sidekickGeneratorReady', () => { - run(); - }); - window.hlx.sidekickGeneratorInstrumented = true; + if (!window.sidekickGeneratorReady) { + // wait for sidekick generator ready event + if (!window.sidekickGeneratorInstrumented) { + window.addEventListener('sidekickGeneratorReady', () => { + run(); + }); + window.sidekickGeneratorInstrumented = true; + } + } else { + run(); } })();