Skip to content

Commit

Permalink
feat: ✨ Adding Rule Management UI
Browse files Browse the repository at this point in the history
Signed-off-by: Nishant Arora <1895906+whizzzkid@users.noreply.github.com>
  • Loading branch information
whizzzkid committed Jul 20, 2023
1 parent 8f0c293 commit 4a9d055
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 2 deletions.
16 changes: 16 additions & 0 deletions add-on/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@
"message": "Experiments",
"description": "A section header on the Preferences screen (option_header_experiments)"
},
"option_header_redirect_rules": {
"message": "Redirect Rules",
"description": "A section header on the Preferences screen (option_header_redirect_rules)"
},
"option_header_reset": {
"message": "Reset Preferences",
"description": "A section header on the Preferences screen (option_header_reset)"
Expand Down Expand Up @@ -507,6 +511,18 @@
"message": "Automatically preload assets imported to IPFS via asynchronous HTTP HEAD requests to a public gateway.",
"description": "An option description on the Preferences screen (option_preloadAtPublicGateway_description)"
},
"option_redirect_rules_reset_all": {
"message": "Reset All Redirect Rules",
"description": "A button label on the Preferences screen (option_redirect_rules_reset_all)"
},
"option_redirect_rules_row_origin": {
"message": "Origin",
"description": "A table header on the Preferences screen (option_redirect_rules_row_origin)"
},
"option_redirect_rules_row_target": {
"message": "Target",
"description": "A table header on the Preferences screen (option_redirect_rules_row_target)"
},
"option_logNamespaces_title": {
"message": "Log Namespaces",
"description": "An option title for tweaking log level (option_logNamespaces_title)"
Expand Down
78 changes: 78 additions & 0 deletions add-on/src/options/forms/redirect-rule-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use strict'
/* eslint-env browser, webextensions */

import browser from 'webextension-polyfill'
import html from 'choo/html/index.js'


/**
*
* @param {(event: string, value?: any) => void} emit
* @returns
*/
function ruleItem(emit) {
/**
* Renders Rule Item
*
* @param {{
* id: string
* origin: string
* target: string
* }} param0
* @returns
*/
return function ({ id, origin, target }) {
return html`
<div class="flex-row-ns pb0-ns">
<dl>
<dt>
<span class="b">${browser.i18n.getMessage('option_redirect_rules_row_origin')}:</span> ${origin}
</dt>
<dt>
<span class="b">${browser.i18n.getMessage('option_redirect_rules_row_target')}:</span> ${target}
</dt>
</dl>
<div class="flex flex-column rule-delete">
<button class="f6 dim br2 ph3 pv2 mb2 mt2 dib white red" onclick=${emit('redirectRuleDeleteRequest', id)}>X</button>
</div>
</div>
`
}
}

/**
*
* @param {{
* emit: (event: string, value?: any) => void,
* redirectRules: {
* id: string
* origin: string
* target: string
* }[]
* }} param0
* @returns
*/
export default function redirectRuleForm({ emit, redirectRules }) {
return html`
<form>
<fieldset class="mb3 pa1 pa4-ns pa3 bg-snow-muted charcoal">
<h2 class="ttu tracked f6 fw4 teal mt0-ns mb3-ns mb1 mt2 ">${browser.i18n.getMessage('option_header_redirect_rules')}</h2>
<div class="flex-row-ns pb0-ns">
<label for="deleteAllRules">
<dl>
<dt>
<div class="self-right-ns">
Found ${redirectRules?.length ?? 0} rules
</div>
</dt>
</dl>
</label>
<div class="self-center-ns">
<button id="deleteAllRules" class="Button transition-all sans-serif v-mid fw5 nowrap lh-copy bn br1 pa2 pointer focus-outline white bg-red white" onclick=${emit('redirectRuleDeleteRequest')}>${browser.i18n.getMessage('option_redirect_rules_reset_all')}</button>
</div>
</div>
${redirectRules ? redirectRules.map(ruleItem(emit)) : html`<div>Loading...</div>`}
</fieldset>
</form>
`
}
7 changes: 6 additions & 1 deletion add-on/src/options/options.css
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ input:invalid {
input.brave {
background-color: #f7f8fa;
}

div.rule-delete {
display: flex;
flex-direction: row;
justify-content: flex-end;
max-width: 50px;
}
6 changes: 6 additions & 0 deletions add-on/src/options/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import apiForm from './forms/api-form.js'
import experimentsForm from './forms/experiments-form.js'
import telemetryForm from './forms/telemetry-form.js'
import resetForm from './forms/reset-form.js'
import redirectRuleForm from './forms/redirect-rule-form.js'
import { supportsBlock } from '../lib/redirect-handler/blockOrObserve.js'

// Render the options page:
// Passed current app `state` from the store and `emit`, a function to create
Expand Down Expand Up @@ -112,6 +114,10 @@ export default function optionsPage (state, emit) {
})}
${resetForm({
onOptionsReset
})}
${supportsBlock ? '' : redirectRuleForm({
redirectRules: state.redirectRules,
emit
})}
</div>
`
Expand Down
13 changes: 12 additions & 1 deletion add-on/src/options/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@

import browser from 'webextension-polyfill'
import { optionDefaults } from '../lib/options.js'
import { notifyOptionChange, notifyStateChange } from '../lib/redirect-handler/blockOrObserve.js'
import { RULE_REGEX_ENDING, notifyOptionChange, notifyStateChange } from '../lib/redirect-handler/blockOrObserve.js'
import createRuntimeChecks from '../lib/runtime-checks.js'
import { handleConsentFromState, trackView } from '../lib/telemetry.js'

// The store contains and mutates the state for the app
export default function optionStore (state, emitter) {
state.options = optionDefaults

const fetchRedirectRules = async () => {
const existingRedirectRules = await browser.declarativeNetRequest.getDynamicRules()
state.redirectRules = existingRedirectRules.map(rule => ({
id: rule.id,
origin: rule.condition.regexFilter?.replace(RULE_REGEX_ENDING, '(.*)').replaceAll('\\', ''),
target: rule.action.redirect?.regexSubstitution?.replace('\\1', '<resource-path>')
}))
emitter.emit('render')
}

const updateStateOptions = async () => {
const runtime = await createRuntimeChecks(browser)
state.withNodeFromBrave = runtime.brave && await runtime.brave.getIPFSEnabled()
Expand All @@ -25,6 +35,7 @@ export default function optionStore (state, emitter) {
handleConsentFromState(state)
trackView('options')
updateStateOptions()
fetchRedirectRules()
browser.storage.onChanged.addListener(updateStateOptions)
})

Expand Down

0 comments on commit 4a9d055

Please sign in to comment.