Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better block creation #24

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/ts/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ browser.commands.onCommand.addListener((command) => {
}).then((tabs) =>
tabs.forEach((tab) => browser.tabs.sendMessage(tab?.id!, command)));
});

browser.runtime.onMessage.addListener((command) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to duplicate code above

browser.tabs.query({
currentWindow: true,
active: true
}).then((tabs) =>
tabs.forEach((tab) => browser.tabs.sendMessage(tab?.id!, command)));
return Promise.resolve('received message: ' + command)
});
41 changes: 14 additions & 27 deletions src/ts/contentScripts/create-block-demo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
import { getFirstTopLevelBlock } from '../../utils/dom';
import { DOM } from '../../utils/dom';
import { Roam} from '../../utils/roam';

export const createDemo = async () => {
await Roam.createBlockAtBottom();
Roam.writeText('bottom-block');
await Roam.createBlockAtBottom(false, 'bottom-block');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverse the order of arguments to match other functions


await Roam.createBlockAtTop();
Roam.writeText('top-block');

await Roam.createFirstChild();
Roam.writeText('first child');

await Roam.createFirstChild();
Roam.writeText('grandchild');

await Roam.activateBlock(getFirstTopLevelBlock());
await Roam.createLastChild();
Roam.writeText('second child');

await Roam.createFirstChild();
Roam.writeText('grandchild');

await Roam.activateBlock(getFirstTopLevelBlock());
await Roam.createDeepestLastDescendant()
Roam.writeText('deepest descendant*');
await Roam.createBlockAtTop(false, 'top-block');
await Roam.createFirstChild('first child');
await Roam.createFirstChild('grandchild');

await Roam.activateBlock(DOM.getFirstTopLevelBlock());
await Roam.createLastChild('second child');
await Roam.createFirstChild('grandchild');

await Roam.activateBlock(getFirstTopLevelBlock());
await Roam.createSiblingBelow()
Roam.writeText('3rd top block');
await Roam.activateBlock(DOM.getFirstTopLevelBlock());
await Roam.createDeepestLastDescendant('deepest descendant*');

await Roam.createSiblingAbove()
Roam.writeText('2nd top block');
await Roam.activateBlock(DOM.getFirstTopLevelBlock());
await Roam.createSiblingBelow('3rd top block');
await Roam.createSiblingAbove('2nd top block');
};
4 changes: 2 additions & 2 deletions src/ts/contentScripts/inc-dec-value/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {browser} from 'webextension-polyfill-ts';
import {getActiveEditElement} from '../../utils/dom';
import {DOM} from '../../utils/dom';


const inputEvent = new Event('input', {
Expand Down Expand Up @@ -98,7 +98,7 @@ const dateModified = (date: Date, modType: string): Date => {
}

const modify = (modType: string) => {
const element = getActiveEditElement() as HTMLTextAreaElement;
const element = DOM.getActiveEditElement() as HTMLTextAreaElement;

if (element.nodeName === 'TEXTAREA') {
const itemContent = element.value;
Expand Down
147 changes: 111 additions & 36 deletions src/ts/utils/dom.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,116 @@
export type ValueElement = HTMLTextAreaElement | HTMLInputElement | HTMLSelectElement;

export function getActiveEditElement(): ValueElement {
// stolen from Surfingkeys. Needs work.

let element = document.activeElement;
// on some pages like chrome://history/, input is in shadowRoot of several other recursive shadowRoots.
while (element?.shadowRoot) {
if (element.shadowRoot.activeElement) {
element = element.shadowRoot.activeElement;
} else {
const subElement = element.shadowRoot.querySelector('input, textarea, select');
if (subElement) {
element = subElement;
export const DOM = {
getActiveEditElement(): ValueElement {
// stolen from Surfingkeys. Needs work.

let element = document.activeElement;
// on some pages like chrome://history/, input is in shadowRoot of several other recursive shadowRoots.
while (element?.shadowRoot) {
if (element.shadowRoot.activeElement) {
element = element.shadowRoot.activeElement;
} else {
const subElement = element.shadowRoot.querySelector('input, textarea, select');
if (subElement) {
element = subElement;
}
break;
}
break;
}
}
return element as ValueElement;
}

export function getTopLevelBlocks() {
return document.querySelector('.roam-article div .flex-v-box') as HTMLElement;
}

export function getLastTopLevelBlock() {
const lastChild = getTopLevelBlocks().lastChild as HTMLElement;
return lastChild.querySelector('.roam-block, textarea') as HTMLElement;
}

export function getFirstTopLevelBlock() {
const firstChild = getTopLevelBlocks().firstChild as HTMLElement;
return firstChild.querySelector('.roam-block, textarea') as HTMLElement;
return element as ValueElement;
},

getTopLevelBlocks() {
return document.querySelector('.roam-article div .flex-v-box') as HTMLElement;
},

getLastTopLevelBlock() {
const lastChild = this.getTopLevelBlocks().lastChild as HTMLElement;
return lastChild.querySelector('.roam-block, textarea') as HTMLElement;
},

getFirstTopLevelBlock() {
const firstChild = this.getTopLevelBlocks().firstChild as HTMLElement;
return firstChild.querySelector('.roam-block, textarea') as HTMLElement;
},


getInputEvent() {
return new Event('input', {
bubbles: true,
cancelable: true,
});
},

async detectChange(fn: () => void, el?: HTMLElement){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe onChange?

const targetNode = el || document.querySelector('.roam-body-main') as HTMLElement;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it a default parameter value?

const config = { attributes: true, childList: true, subtree: true };
return new Promise(async resolve => {
//@ts-ignore unused arg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just name it _ , also I'd probably inline callback

const callback = function(mutationsList:MutationRecord[], observer: MutationObserver) {
resolve('mutated')
observer.disconnect();
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
await fn();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my IDE tells me that the await is redundant here. or should fn return promise?

})
},

getBlockContainer(element?: HTMLElement) {
let parent = null;
let el = element || document.querySelector('textarea') as HTMLElement
while(el && !parent){
if (el.parentElement?.className?.includes('flex-v-box roam-block-container')) {
parent = el?.parentElement;
}
el = el?.parentElement as HTMLElement;
}
Comment on lines +63 to +68
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can query for parent with particular class - see example in my cr https://github.com/roam-unofficial/roam-toolkit/pull/22/files#diff-7f9ad9f2be2cc289f31a201fca94d43cR24

return parent as HTMLElement
},

getBlockParent(element: HTMLElement){
return this.getBlockContainer(this.getBlockContainer(element));
},

isTopLevelBlock(element: HTMLElement){
return !this.getBlockParent(element);
},

hasChildren(element: HTMLElement){
return !!this.getBlockChildren(element)?.length;
},

getBlockChildren(element: HTMLElement) : HTMLCollection{
const childrenDiv = this.getBlockContainer(element)?.lastChild as HTMLElement;
return childrenDiv?.children;
},
getNthChild(element: HTMLElement, n:number){
return this.getBlockChildren(element)?.[n].querySelector('.roam-block') as HTMLElement;
},
getFirstChild(element: HTMLElement){
return this.getNthChild(element, 0);
},
getLastChild(element: HTMLElement){
return this.getNthChild(element,this.getBlockChildren(element).length-1);
},
hasSiblings(element: HTMLElement) {
return !!this.getSiblings(element)
},
getSiblings(element: HTMLElement): HTMLCollection {
if (this.isTopLevelBlock(element)) {
return this.getBlockContainer(element)?.parentElement?.children as HTMLCollection
} else {
return this.getBlockChildren(this.getBlockParent(element))
}
},
getNthSibling(element:HTMLElement, n:number) {
return this.getSiblings(element)?.[n].querySelector('.roam-block');
},
getFirstSibling(element: HTMLElement){
return this.getNthSibling(element, 0);
},
getLastSibling(element: HTMLElement){
return this.getNthSibling(element,this.getSiblings(element).length-1);
},
}
Comment on lines +107 to 116
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should just apply .querySelector('.roam-block'); before we return results from getSiblings and return the array of that. Then we won't need these specialized methods.

Similarly for the children


export function getInputEvent() {
return new Event('input', {
bubbles: true,
cancelable: true,
});
}
8 changes: 4 additions & 4 deletions src/ts/utils/keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ export const Keyboard = {
UP_ARROW: 38,
RIGHT_ARROW: 39,
DOWN_ARROW: 40,
BASE_DELAY: 20,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that a minimal viable delay now? :(

BASE_DELAY: 50,

async simulateKey(code: number, delayOverride: number = 0, opts?: KeyboardEventInit) {
const event = new KeyboardEvent('keydown', {
bubbles: true,
cancelable: true,
// @ts-ignore
// @ts-ignore
keyCode: code,
...opts
});
document?.activeElement?.dispatchEvent(event);
return delay(delayOverride ||this.BASE_DELAY);
document?.activeElement?.dispatchEvent(event)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

return delay(delayOverride || this.BASE_DELAY);
},
async pressEnter(delayOverride: number = 0) {
return this.simulateKey(13, delayOverride)
Expand Down
Loading