diff --git a/pkg/extension/src/scripts/content/toast.js b/pkg/extension/src/scripts/content/toast.js
index 1751b497f..31a519f41 100644
--- a/pkg/extension/src/scripts/content/toast.js
+++ b/pkg/extension/src/scripts/content/toast.js
@@ -279,7 +279,6 @@
}
function toggleRow(rowId) {
- console.log('currentToastEl: ', currentToastEl)
const container = currentToastEl.shadowRoot.querySelector(rowId)
const initialState = container?.getAttribute('data-state')
const rows = currentToastEl.shadowRoot.querySelectorAll(
@@ -361,7 +360,7 @@
})
}
- function createLabelRow(label, idx) {
+ function createLabelRow(label) {
const element = document.createElement('button')
const dot = document.createElement('span')
dot.style = 'width:10px;height:10px;border-radius:1000px;'
@@ -384,9 +383,8 @@
element.appendChild(check)
element.onclick = labelClick
- element.onkeydown = labelKeyDown
+ element.onkeydown = labelEditorKeyDownHandler
element.setAttribute('data-label-id', label.id)
- element.setAttribute('data-label-idx', idx)
element.setAttribute(
'data-label-selected',
label['selected'] ? 'on' : 'off'
@@ -421,68 +419,117 @@
if (label) {
label.selected = toggledValue
}
+
+ const labelList = event.target.form.querySelector('#label-list')
+ const labelInput = event.target.form.querySelector(
+ '#omnivore-edit-label-input'
+ )
+ if (toggledValue) {
+ addLabel(labelList, labelInput, label.name)
+ } else {
+ removeLabel(labelList, label.id)
+ }
}
- function labelKeyDown(event) {
+ function backspaceOnLastItem(labelsList, labelsInput) {
+ // Get the last
item before the {
+ node.removeAttribute('data-label-backspaced')
+ })
+ }
+
+ function labelEditorKeyDownHandler(event) {
event.cancelBubble = true
if (event.stopPropogation) {
event.stopPropogation()
}
+ // If any labels have been backspaced into (so they have the selected outline), clear their state
+ if (event.target.form && event.key.toLowerCase() !== 'backspace') {
+ clearBackspacedLabels(event.target.form)
+ }
+
switch (event.key.toLowerCase()) {
case 'arrowup': {
- if (
- event.target ==
- event.target.form.querySelector('#omnivore-edit-label-text')
- ) {
+ if (event.target.id == 'omnivore-edit-label-input') {
return
}
- const idx = event.target.getAttribute('data-label-idx')
- let prevIdx = idx && Number(idx) != NaN ? Number(idx) - 1 : 0
- if (
- event.target ==
- event.target.form.querySelector('#omnivore-save-button')
- ) {
- // Focus the last label index
- const maxItemIdx = Math.max(
- ...Array.from(
- event.target.form.querySelectorAll(`button[data-label-idx]`)
- ).map((b) => Number(b.getAttribute('data-label-idx')))
- )
- if (maxItemIdx != NaN) {
- prevIdx = maxItemIdx
- }
+ if (!event.target.getAttribute('data-label-id')) {
+ return
}
- const prev = event.target.form.querySelector(
- `button[data-label-idx='${prevIdx}']`
- )
- if (prev) {
+ let prev = event.target.previousElementSibling
+ if (prev && prev.getAttribute('data-label-id')) {
prev.focus()
} else {
- // Focus the text area
- event.target.form.querySelector('#omnivore-edit-label-text')?.focus()
+ event.target.form.querySelector('#omnivore-edit-label-input')?.focus()
}
event.preventDefault()
break
}
case 'arrowdown': {
- const idx = event.target.getAttribute('data-label-idx')
- const nextIdx = idx && Number(idx) != NaN ? Number(idx) + 1 : 0
- const next = event.target.form.querySelector(
- `button[data-label-idx='${nextIdx}']`
- )
- if (next) {
- next.focus()
+ let next = undefined
+ if (event.target.id == 'omnivore-edit-label-input') {
+ idx = event.target.getAttribute('data-label-id')
+ next = event.target
+ .closest('#omnivore-edit-labels-form')
+ .querySelector('#omnivore-edit-labels-list')
+ .querySelector('[data-label-id]')
} else {
- // Focus the save button
- event.target.form.querySelector('.omnivore-save-button')?.focus()
+ next = event.target.nextElementSibling
+ }
+
+ if (next && next.getAttribute('data-label-id')) {
+ next.focus()
}
event.preventDefault()
break
}
+ case 'backspace': {
+ if (
+ event.target.id == 'omnivore-edit-label-input' &&
+ event.target.value.length == 0
+ ) {
+ const labelList = event.target.form.querySelector('#label-list')
+ backspaceOnLastItem(labelList, event.target)
+ }
+ break
+ }
case 'enter': {
+ if (event.target.id == 'omnivore-edit-label-input') {
+ if (event.target.value) {
+ const labelList = event.target.form.querySelector('#label-list')
+ addLabel(labelList, event.target, event.target.value)
+ }
+ event.preventDefault()
+ return
+ }
const labelId = event.target.getAttribute('data-label-id')
toggleLabel(event, labelId)
event.preventDefault()
@@ -529,7 +576,6 @@
currentToastEl.shadowRoot.querySelector(
'#omnivore-add-note-form'
).onsubmit = (event) => {
- console.log('submitting form: ', event)
updateStatusBox('#omnivore-add-note-status', 'loading', 'Adding note...')
browserApi.runtime.sendMessage({
@@ -585,6 +631,143 @@
}
}
+ function getRandomColor() {
+ const colors = [
+ '#FF5D99',
+ '#7CFF7B',
+ '#FFD234',
+ '#7BE4FF',
+ '#CE88EF',
+ '#EF8C43',
+ ]
+ const randomIndex = Math.floor(Math.random() * colors.length)
+ return colors[randomIndex]
+ }
+
+ function getTempUUID() {
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
+ (
+ c ^
+ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
+ ).toString(16)
+ )
+ }
+
+ function addLabel(labelList, labelInput, labelValue) {
+ // first check if the label is already entered:
+ const existingLabel = labels.find((l) => l.name === labelValue)
+ const labelEntryItem = labelList.querySelector('#label-entry-item')
+ const inputItem = labelEntryItem.querySelector('#omnivore-edit-label-input')
+
+ // Handle case where label is already selected
+ if (
+ existingLabel &&
+ labelList.querySelector(`[data-label-id='${existingLabel.id}']`)
+ ) {
+ const labelItem = labelList.querySelector(
+ `[data-label-id='${existingLabel.id}']`
+ )
+ labelItem.setAttribute('data-item-highlighted', 'on')
+ setTimeout(() => {
+ labelItem.style.borderColor = 'rgb(222, 222, 222)'
+ }, 500)
+
+ if (inputItem) {
+ inputItem.value = ''
+ inputItem.focus()
+ updateLabels(undefined)
+ }
+ return
+ }
+
+ const labelColor = existingLabel ? existingLabel.color : getRandomColor()
+ const labelElem = document.createElement('li')
+ labelElem.classList.add('label')
+ labelElem.innerHTML = `
+
+ ${labelValue}
+
+ `
+
+ labelList.insertBefore(labelElem, labelEntryItem)
+ labelInput.value = ''
+
+ const form = labelList.closest('#omnivore-edit-labels-form')
+ if (existingLabel) {
+ const element = form.querySelector(
+ `[data-label-id='${existingLabel.id}']`
+ )
+ existingLabel.selected = true
+ element.setAttribute('data-label-selected', 'on')
+ labelElem.setAttribute('data-label-id', existingLabel.id)
+ } else {
+ // insert a toggle row at the top
+ const rowList = form.querySelector('#omnivore-edit-labels-list')
+ const newLabel = {
+ id: getTempUUID(),
+ color: labelColor,
+ name: labelValue,
+ temporary: true,
+ selected: true,
+ }
+ labels.push(newLabel)
+ labelElem.setAttribute('data-label-id', newLabel.id)
+
+ // Now prepend a label in the rows at the bottom
+ const rowHtml = createLabelRow(newLabel)
+ const firstRow = rowList.querySelector('button[data-label-id]')
+ rowHtml.setAttribute('data-label-selected', 'on')
+ rowList.insertBefore(rowHtml, firstRow)
+ }
+
+ if (inputItem) {
+ inputItem.focus()
+ updateLabels(undefined)
+ }
+
+ syncLabelChanges()
+ }
+
+ function removeLabel(labelList, labelID) {
+ const form = labelList.closest('#omnivore-edit-labels-form')
+ const element = labelList.querySelector(`[data-label-id='${labelID}']`)
+ if (element) {
+ element.remove()
+ }
+
+ const rowElement = form.querySelector(`[data-label-id='${labelID}']`)
+ if (rowElement) {
+ rowElement.setAttribute('data-label-selected', 'off')
+ }
+
+ updateLabels()
+ }
+
+ function syncLabelChanges() {
+ console.log('syncLabels')
+
+ updateStatusBox(
+ '#omnivore-edit-labels-status',
+ 'loading',
+ 'Updating Labels...',
+ undefined
+ )
+ const labelIds = labels.filter((l) => l['selected']).map((l) => l.id)
+
+ // browserApi.runtime.sendMessage({
+ // - action: ACTIONS.SetLabels,
+ // - payload: {
+ // - ctx: ctx,
+ // - labelIds: labelIds,
+ // - },
+ // - })
+ }
+
async function editLabels() {
cancelAutoDismiss()
@@ -594,47 +777,33 @@
toggleRow('#omnivore-edit-labels-row')
currentToastEl.shadowRoot
- .querySelector('#omnivore-edit-label-text')
+ .querySelector('#omnivore-edit-label-input')
?.focus()
const list = currentToastEl.shadowRoot.querySelector(
'#omnivore-edit-labels-list'
)
- currentToastEl.shadowRoot
- .querySelector('#omnivore-edit-label-text')
- .addEventListener('input', function () {
- updateLabels(this.value)
- })
currentToastEl.shadowRoot.querySelector(
- '#omnivore-edit-label-text'
- ).onkeydown = labelKeyDown
+ '#omnivore-edit-label-input'
+ ).onkeydown = labelEditorKeyDownHandler
+
+ currentToastEl.shadowRoot.querySelector(
+ '#omnivore-edit-label-editor'
+ ).onclick = labelEditorClickHandler
+
+ currentToastEl.shadowRoot
+ .querySelector('#omnivore-edit-label-input')
+ .addEventListener('input', (event) => {
+ updateLabels(event.target.value)
+ })
if (list) {
list.innerHTML = ''
labels.forEach(function (label, idx) {
- const rowHtml = createLabelRow(label, idx)
+ const rowHtml = createLabelRow(label)
list.appendChild(rowHtml)
})
}
-
- currentToastEl.shadowRoot.querySelector(
- '#omnivore-edit-labels-form'
- ).onsubmit = (event) => {
- event.preventDefault()
- const statusBox = currentToastEl.shadowRoot.querySelector(
- '#omnivore-edit-labels-status'
- )
- statusBox.innerText = 'Updating labels...'
- const labelIds = labels.filter((l) => l['selected']).map((l) => l.id)
-
- browserApi.runtime.sendMessage({
- action: ACTIONS.SetLabels,
- payload: {
- ctx: ctx,
- labelIds: labelIds,
- },
- })
- }
}
async function updateLabels(filterValue) {
@@ -648,13 +817,13 @@
.filter(
(l) => l.name.toLowerCase().indexOf(filterValue.toLowerCase()) > -1
)
- .forEach(function (label, idx) {
- const rowHtml = createLabelRow(label, idx)
+ .forEach(function (label) {
+ const rowHtml = createLabelRow(label)
list.appendChild(rowHtml)
})
} else {
- labels.forEach(function (label, idx) {
- const rowHtml = createLabelRow(label, idx)
+ labels.forEach(function (label) {
+ const rowHtml = createLabelRow(label)
list.appendChild(rowHtml)
})
}
diff --git a/pkg/extension/src/views/toast.html b/pkg/extension/src/views/toast.html
index 31bf5c65b..3130869be 100644
--- a/pkg/extension/src/views/toast.html
+++ b/pkg/extension/src/views/toast.html
@@ -68,6 +68,11 @@
line-height: 20px;
text-align: center;
}
+ #omnivore-toast-container #omnivore-edit-labels-status {
+ height: 22px;
+ padding-top: 10px;
+ }
+
#omnivore-toast-button-row {
gap: 5px;
align-items: center;
@@ -228,7 +233,7 @@
max-height: 200px;
gap: 5px;
color: #3B3A38;
- margin-top: 15px;
+ margin-top: 0px;
margin-bottom: 10px;
}
@@ -331,6 +336,86 @@
}
}
+
+