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

adds live page preview on hover :) #52

Merged
merged 34 commits into from May 17, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e1e5c57
adds page preview on hover :)
May 10, 2020
9c06df6
disable preview on toggle
May 11, 2020
b9ee395
use popper for positioning
May 12, 2020
c16e1ba
remove popper if item is removed from dom
May 12, 2020
9c60b20
set scrollTop to 0 for next hover
May 12, 2020
fc3a3d3
support page-ref-tag
May 12, 2020
8a7183e
- disable by default;
May 15, 2020
62d7a67
add warning tooltip, uses react-tooltip-popper
May 15, 2020
53f03d2
rename warningTooltip -> warning
May 16, 2020
db31638
fix: reducer
May 16, 2020
dcfc937
refactor to PreviewIframe class
May 16, 2020
806203d
refactor Tooltip
May 16, 2020
79d4dca
revert manifest.json
May 16, 2020
282f915
clear instance on disable
May 16, 2020
3129b48
Merge commit 'c9593ccce94a31f18bc60b2acbfac5f10b7b7a5e' into live-pre…
May 16, 2020
e29481d
chore: private functions
May 16, 2020
6740221
move initial state to function
May 16, 2020
99338a9
add comment for hack
May 16, 2020
02c9db7
use daily notes page for first load
May 16, 2020
cece075
rename function
May 16, 2020
eabd431
Merge commit 'a955330ee4859b3c7dc88b1bf3bb8cbd0c845aa7' into live-pre…
May 16, 2020
bb08eae
review changes
May 16, 2020
ea574cd
fix comment
May 16, 2020
53459da
fix: condition
May 16, 2020
b64069e
remove log
May 16, 2020
cc7e463
fix: mouse handling
May 16, 2020
13af95d
remove body check
May 16, 2020
5a8d720
review
May 16, 2020
9afd28e
fix: create iframe in constructor,
May 17, 2020
7210520
fix: navigation function
May 17, 2020
73004cf
fix: type
May 17, 2020
f01d18e
Merge remote-tracking branch 'origin/master' into live-preview
May 17, 2020
caff0e7
move live-preview file, add to features
May 17, 2020
aa798b7
remove exisitingIframe check,
May 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
114 changes: 44 additions & 70 deletions src/ts/contentScripts/live-preview/index.tsx
Expand Up @@ -25,24 +25,25 @@ browser.runtime.onMessage.addListener(async message => {
let iframeInstance: PreviewIframe | null = null

const toggleIframe = (active: boolean) => {
if (!iframeInstance) {
if (active && !iframeInstance) {
iframeInstance = new PreviewIframe()
}
if (active) {
iframeInstance.activate()
} else {
} else if (iframeInstance) {
iframeInstance.destroy()
iframeInstance = null
}
}

class PreviewIframe {
iframeId = 'roam-toolkit-iframe-preview'
iframe: HTMLIFrameElement | null = null
iframe: HTMLIFrameElement
popupTimeout: ReturnType<typeof setTimeout> | null = null
hoveredElement: HTMLElement | null = null
popper: Instance | null = null
popupTimeoutDuration = 300
constructor() {
this.iframe = document.createElement('iframe')
}
activate() {
this.initPreviewIframe()
}
Expand All @@ -61,40 +62,34 @@ class PreviewIframe {

private removeIframe() {
const isCurrentIframePresent = document.body.contains(this.iframe)
if (!this.iframe || !isCurrentIframePresent) {
if (!isCurrentIframePresent) {
return
}
if (isCurrentIframePresent) {
document.body.removeChild(this.iframe)
}
if (this.iframe) {
this.iframe = null
}
}

private getIFrameByUrl(url: string): HTMLIFrameElement | null {
return document.querySelector(`iframe[src="${url}"]`)
document.body.removeChild(this.iframe)
}
Copy link
Member

Choose a reason for hiding this comment

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

a nit, but can the prettier be configured to require at list 1 space between functions? 😛

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Stvad Haha, I wish 😅 It is not possible in prettier because of the way prettier works (rewriting your code). See this more more info

It turns out that empty lines are very hard to automatically generate. The approach that Prettier takes is to preserve empty lines the way they were in the original source code
https://prettier.io/docs/en/rationale.html#empty-lines

Copy link
Member

Choose a reason for hiding this comment

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

huh, interesting. May I suggest you configure your IDE to do so then ?😛

private getVisibleIframeByUrl(url: string): HTMLIFrameElement | null {
const iframe = this.getIFrameByUrl(url)
return iframe?.style.opacity === '1' ? iframe : null
/**
* HACK: needed because the instance is created thrice onload/toggle.
* Remove this check to see the issue
*/
private getExisitingIframe(): HTMLIFrameElement | null {
return document.getElementById(this.iframeId) ? this.iframe : null
}

private initPreviewIframe() {
const url = Navigation.getPageUrl()
const existingIframe = this.getIFrameByUrl(url)
const url = Navigation.getDailyNotesUrl()
const existingIframe = this.getExisitingIframe()
if (existingIframe) {
Copy link
Member

Choose a reason for hiding this comment

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

I hope we'd be getting rid of this now. but if we were not - I think the assignment would have been still required, to ensure that we operate on the appropriate underlying object

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this can be removed after #58 gets merged. I tested by merging with #57 already :)

this.iframe = existingIframe
return
}
this.iframe = this.setupHiddenIframe(url)
this.setupHiddenIframe(url)
this.addIframeToBody()
this.scrollToTopHack()
this.attachMouseListeners()
}

private addIframeToBody() {
if (this.iframe) document.body.appendChild(this.iframe)
document.body.appendChild(this.iframe)
}

private attachMouseListeners() {
Expand All @@ -113,7 +108,7 @@ class PreviewIframe {
const text = this.getTargetInnerText(target)
this.hoveredElement = target
const url = Navigation.getPageUrlByName(text)
if (this.iframe && url) {
if (url) {
this.prepIframeForDisplay(url)
this.setTimerForPopup(target)
}
Expand Down Expand Up @@ -143,10 +138,8 @@ class PreviewIframe {
private setTimerForPopup(target: HTMLElement) {
if (!this.popupTimeout) {
this.popupTimeout = window.setTimeout(() => {
if (this.iframe) {
this.showPreview()
this.makePopper(target)
}
this.showPreview()
this.makePopper(target)
}, this.popupTimeoutDuration)
}
}
Expand All @@ -173,17 +166,15 @@ class PreviewIframe {
}

private resetIframeForNextHover() {
if (this.iframe) {
this.scrollToTopOnMouseOut()
this.iframe.style.pointerEvents = 'none'
this.iframe.style.opacity = '0'
this.iframe.style.height = '0'
this.iframe.style.width = '0'
}
this.scrollToTopOnMouseOut()
this.iframe.style.pointerEvents = 'none'
this.iframe.style.opacity = '0'
this.iframe.style.height = '0'
this.iframe.style.width = '0'
}

private scrollToTopOnMouseOut() {
Copy link
Member

Choose a reason for hiding this comment

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

nit: can you place the scroll to top hacks close to each other and extract commonality between them?

if (this.iframe?.contentDocument) {
if (this.iframe.contentDocument) {
// scroll to top when removed, so the next popup is not scrolled
const scrollContainer = this.iframe.contentDocument.querySelector('.roam-center > div')
if (scrollContainer) {
Expand All @@ -193,20 +184,10 @@ class PreviewIframe {
}

private showPreview() {
if (this.iframe) {
this.iframe.style.opacity = '1'
this.iframe.style.pointerEvents = 'all'
}
this.iframe.style.opacity = '1'
this.iframe.style.pointerEvents = 'all'
}
private prepIframeForDisplay(url: string) {
if (!this.iframe) {
return
}
const visibleIframe = this.getVisibleIframeByUrl(url)
if (visibleIframe) {
// if visible, just return the iframe
return
}
// this pre-loads the iframe, (which is shown after a delay)
this.iframe.src = url
this.iframe.style.height = '500px'
Expand All @@ -215,9 +196,6 @@ class PreviewIframe {
}

private makePopper(target: HTMLElement) {
if (!this.iframe) {
return
}
this.popper = createPopper(target, this.iframe, {
placement: 'right',
modifiers: [
Expand All @@ -238,25 +216,22 @@ class PreviewIframe {
}

private setupHiddenIframe = (url: string) => {
let iframe = document.createElement('iframe')
iframe.src = url
iframe.style.position = 'absolute'
iframe.style.left = '0'
iframe.style.top = '0'
iframe.style.opacity = '0'
iframe.style.pointerEvents = 'none'
iframe.style.height = '0'
iframe.style.width = '0'
iframe.style.border = '0'
iframe.style.boxShadow = '0 0 4px 5px rgba(0, 0, 0, 0.2)'
iframe.style.borderRadius = '4px'
iframe.id = this.iframeId
iframe = this.appendStylesToIFrameOnLoad(iframe)

return iframe
this.iframe.src = url
this.iframe.style.position = 'absolute'
this.iframe.style.left = '0'
this.iframe.style.top = '0'
this.iframe.style.opacity = '0'
this.iframe.style.pointerEvents = 'none'
this.iframe.style.height = '0'
this.iframe.style.width = '0'
this.iframe.style.border = '0'
this.iframe.style.boxShadow = '0 0 4px 5px rgba(0, 0, 0, 0.2)'
this.iframe.style.borderRadius = '4px'
this.iframe.id = this.iframeId
this.appendStylesToIFrameOnLoad()
}

private appendStylesToIFrameOnLoad = (iframe: HTMLIFrameElement) => {
private appendStylesToIFrameOnLoad = () => {
const styleNode = document.createElement('style')
styleNode.innerHTML = `
.roam-topbar {
Expand All @@ -272,10 +247,9 @@ class PreviewIframe {
display: none !important;
}
`
iframe.onload = (event: Event) => {
this.iframe.onload = (event: Event) => {
;(event.target as HTMLIFrameElement).contentDocument?.body.appendChild(styleNode)
}
return iframe
}
/**
* HACK: to reset scroll after adding iframe to DOM.
Expand Down
8 changes: 4 additions & 4 deletions src/ts/roam/navigation.ts
Expand Up @@ -25,10 +25,10 @@ export const Navigation = {
}
return this.getPageUrl(page[':block/uid'])
},
getPageUrl(uid?: string) {
if (!uid) {
return this.baseUrl().toString()
}
getDailyNotesUrl() {
return this.baseUrl().toString()
},
getPageUrl(uid: string) {
return this.basePageUrl().toString() + '/' + uid
},
currentPageUid() {
Expand Down
2 changes: 1 addition & 1 deletion src/ts/utils/settings.ts
Expand Up @@ -60,7 +60,7 @@ export const prepareSettings = (features: Feature[]): Feature[] => {
payload: active,
})

const initialState: any = initDefaultState(feature)
const initialState = initDefaultState(feature)

let reducers: any = {
[`${feature.id}_toggle`]: (state: any, action: any) => {
Expand Down