Skip to content

Commit

Permalink
feat(selection): support selection on internal pages
Browse files Browse the repository at this point in the history
  • Loading branch information
crimx committed Jul 18, 2018
1 parent edd5fa9 commit 226be86
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 115 deletions.
24 changes: 24 additions & 0 deletions src/_helpers/injectSaladictInternal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export function injectSaladictInternal (noInjectContentCSS?: boolean) {
const $scriptSelection = document.createElement('script')
$scriptSelection.src = './selection.js'
$scriptSelection.type = 'text/javascript'

const $scriptContent = document.createElement('script')
$scriptContent.src = './content.js'
$scriptContent.type = 'text/javascript'

const $styleContent = document.createElement('link')
$styleContent.href = './content.css'
$styleContent.rel = 'stylesheet'

const $stylePanel = document.createElement('link')
$stylePanel.href = './panel-internal.css'
$stylePanel.rel = 'stylesheet'

document.body.appendChild($scriptSelection)
document.body.appendChild($scriptContent)
if (!noInjectContentCSS) {
document.head.appendChild($styleContent)
}
document.head.appendChild($stylePanel)
}
10 changes: 5 additions & 5 deletions src/_helpers/promise-more.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/**
* Like Promise.all but always resolves.
*/
export function reflect (iterable: ArrayLike<any>): Promise<any[]> {
export function reflect<T> (iterable: ArrayLike<T | PromiseLike<T>>): Promise<T[]> {
const arr = Array.isArray(iterable) ? iterable : Array.from(iterable)
return Promise.all(arr.map(p => Promise.resolve(p).catch(() => null)))
}

/**
* Like Promise.all but only rejects when all are failed.
*/
export function any (iterable: ArrayLike<any>): Promise<any[]> {
export function any<T> (iterable: ArrayLike<T | PromiseLike<T>>): Promise<T[]> {
const arr = Array.isArray(iterable) ? iterable : Array.from(iterable)

let rejectCount = 0
Expand All @@ -34,15 +34,15 @@ export function any (iterable: ArrayLike<any>): Promise<any[]> {
* Returns the first resolved value as soon as it is resolved.
* Fails when all are failed.
*/
export function first (iterable: ArrayLike<any>): Promise<any> {
export function first<T extends any> (iterable: ArrayLike<T | PromiseLike<T>>): Promise<T> {
const arr = Array.isArray(iterable) ? iterable : Array.from(iterable)

let rejectCount = 0
return new Promise((resolve, reject) =>
arr.map((p, i) => {
arr.forEach(p => {
Promise.resolve(p)
.then(resolve)
.catch(e => {
.catch(() => {
if (++rejectCount === arr.length) {
reject(new Error('All rejected'))
}
Expand Down
6 changes: 3 additions & 3 deletions src/_locales/options/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,9 @@
"zh_TW": "添加生字"
},
"panelmode_description": {
"en": "Inside dict panel. See 'Search Mode' above. <p class=\"hl\">Note that it won't affect the dict panel on this page.</p>",
"zh_CN": "查词面板内部的查词模式。参见上方“查词模式”。<p class=\"hl\">注意在本页面的查词面板上没有效果。</p>",
"zh_TW": "字典視窗內部的查字模式。參見上方「查字模式」。<p class=\"hl\">注意在本窗口的字典視窗介面中沒有效果。</p>"
"en": "Inside dict panel. See 'Search Mode' above.",
"zh_CN": "查词面板内部的查词模式。参见上方“查词模式”。",
"zh_TW": "字典視窗內部的查字模式。參見上方「查字模式」。"
},
"panelmode_title": {
"en": "Panel Mode",
Expand Down
25 changes: 25 additions & 0 deletions src/content/components/DictPanel/_style.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
.panel-FrameBody {
height: 100vh;
margin: 0;
padding: 0;
}

.panel-Root {
box-sizing: border-box;
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;
margin: 0;
padding: 0;
background-color: #fff;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica, Arial, "Hiragino Sans GB", "Hiragino Sans GB W3", "Microsoft YaHei UI", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;

*, *:before, *:after {
box-sizing: inherit;
}
}

.panel-DictContainer {
flex: 1;
overflow-x: hidden;
Expand Down
6 changes: 4 additions & 2 deletions src/content/components/DictPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type ChildrenProps =
>

export interface DictPanelProps extends ChildrenProps {
readonly isAnimation: boolean
readonly dictionaries: DictionariesState['dictionaries']
readonly allDictsConfig: DictConfigs
readonly langCode: AppConfig['langCode']
Expand All @@ -36,6 +37,7 @@ export interface DictPanelProps extends ChildrenProps {
export default class DictPanel extends React.Component<DictPanelProps> {
render () {
const {
isAnimation,
isFav,
isPinned,
langCode,
Expand Down Expand Up @@ -63,7 +65,7 @@ export default class DictPanel extends React.Component<DictPanelProps> {
} = dictionaries

return (
<>
<div className={`panel-Root${isAnimation ? ' isAnimate' : ''}`}>
{React.createElement(MenuBar, {
isFav,
isPinned,
Expand Down Expand Up @@ -98,7 +100,7 @@ export default class DictPanel extends React.Component<DictPanelProps> {
})
})}
</div>
</>
</div>
)
}
}
57 changes: 37 additions & 20 deletions src/content/components/DictPanelPortal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DictPanel, { DictPanelDispatchers, DictPanelProps } from '../DictPanel'
import { Omit } from '@/typings/helpers'
import PortalFrame from '@/components/PortalFrame'

const isSaladictInternalPage = !!window.__SALADICT_INTERNAL_PAGE__
const isSaladictPopupPage = !!window.__SALADICT_POPUP_PAGE__
const isSaladictOptionsPage = !!window.__SALADICT_OPTIONS_PAGE__

Expand Down Expand Up @@ -116,9 +117,16 @@ export default class DictPanelPortal extends React.Component<DictPanelPortalProp
handleDragStart = (clientX, clientY) => {
const activeElement = document.activeElement as any
if (activeElement) { activeElement.blur() }
// e is from iframe, so there is offset
this.lastMouseX = clientX + this.props.panelRect.x
this.lastMouseY = clientY + this.props.panelRect.y

if (isSaladictInternalPage) {
this.lastMouseX = clientX
this.lastMouseY = clientY
} else {
// e is from iframe, so there is offset
this.lastMouseX = clientX + this.props.panelRect.x
this.lastMouseY = clientY + this.props.panelRect.y
}

this.setState({ isDragging: true })
window.addEventListener('mousemove', this.handleWindowMouseMove, { capture: true })
window.addEventListener('touchmove', this.handleWindowTouchMove, { capture: true })
Expand Down Expand Up @@ -246,21 +254,30 @@ export default class DictPanelPortal extends React.Component<DictPanelPortalProp
+ (isDragging ? ' isDragging' : '')

return (
<PortalFrame
className={frameClassName}
bodyClassName={isAnimation ? 'isAnimate' : undefined}
name='saladict-dictpanel'
frameBorder='0'
head={this.frameHead}
frameDidMount={this.frameDidMount}
>
<DictPanel
{...this.props}
panelWidth={this.props.panelRect.width}
handleDragAreaMouseDown={this.handleDragAreaMouseDown}
handleDragAreaTouchStart={this.handleDragAreaTouchStart}
/>
</PortalFrame>
isSaladictInternalPage
? <div className={'panel-StyleRoot ' + frameClassName}>
<DictPanel
{...this.props}
panelWidth={this.props.panelRect.width}
handleDragAreaMouseDown={this.handleDragAreaMouseDown}
handleDragAreaTouchStart={this.handleDragAreaTouchStart}
/>
</div>
: <PortalFrame
className={frameClassName}
bodyClassName='panel-FrameBody'
name='saladict-dictpanel'
frameBorder='0'
head={this.frameHead}
frameDidMount={this.frameDidMount}
>
<DictPanel
{...this.props}
panelWidth={this.props.panelRect.width}
handleDragAreaMouseDown={this.handleDragAreaMouseDown}
handleDragAreaTouchStart={this.handleDragAreaTouchStart}
/>
</PortalFrame>
)
}

Expand All @@ -283,8 +300,8 @@ export default class DictPanelPortal extends React.Component<DictPanelPortalProp
return ReactDOM.createPortal(
<div
className='saladict-DIV'
onMouseMoveCapture={isDragging ? this.handleFrameMouseMove : undefined}
onTouchMoveCapture={isDragging ? this.handleFrameTouchMove : undefined}
onMouseMoveCapture={!isSaladictInternalPage && isDragging ? this.handleFrameMouseMove : undefined}
onTouchMoveCapture={!isSaladictInternalPage && isDragging ? this.handleFrameTouchMove : undefined}
onMouseUpCapture={isDragging ? this.handleDragEnd : undefined}
onTouchEndCapture={isDragging ? this.handleDragEnd : undefined}
onKeyUp={this.handleFrameKeyUp}
Expand Down
4 changes: 3 additions & 1 deletion src/content/redux/modules/dictionaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const isSaladictOptionsPage = !!window.__SALADICT_OPTIONS_PAGE__
const isSaladictInternalPage = !!window.__SALADICT_INTERNAL_PAGE__
const isSaladictPopupPage = !!window.__SALADICT_POPUP_PAGE__

const isNoSearchHistoryPage = isSaladictInternalPage && !isSaladictPopupPage

let _searchDelayTimeout: any = null

/*-----------------------------------------------*\
Expand Down Expand Up @@ -338,7 +340,7 @@ export function searchText (arg?: { id?: DictID, info?: SelectionInfo }): Dispat
}
})

if (!isSaladictInternalPage &&
if (!isNoSearchHistoryPage &&
state.config.searhHistory &&
(!browser.extension.inIncognitoContext || state.config.searhHistoryInco) &&
!isSameSelection(state.config.searhHistory[0], info)
Expand Down
12 changes: 2 additions & 10 deletions src/history/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import React from 'react'
import ReactDOM from 'react-dom'
import WordPage from '@/components/WordPage'
import { injectSaladictInternal } from '@/_helpers/injectSaladictInternal'

window.__SALADICT_INTERNAL_PAGE__ = true

// inject panel first(but after global flags) to listen to page event
const $scriptSelection = document.createElement('script')
$scriptSelection.src = './selection.js'
$scriptSelection.type = 'text/javascript'

const $scriptContent = document.createElement('script')
$scriptContent.src = './content.js'
$scriptContent.type = 'text/javascript'

document.body.appendChild($scriptSelection)
document.body.appendChild($scriptContent)
injectSaladictInternal()

ReactDOM.render(<WordPage area='history' />, document.getElementById('root'))
12 changes: 2 additions & 10 deletions src/notebook/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import React from 'react'
import ReactDOM from 'react-dom'
import WordPage from '@/components/WordPage'
import { injectSaladictInternal } from '@/_helpers/injectSaladictInternal'

window.__SALADICT_INTERNAL_PAGE__ = true

// inject panel first(but after global flags) to listen to page event
const $scriptSelection = document.createElement('script')
$scriptSelection.src = './selection.js'
$scriptSelection.type = 'text/javascript'

const $scriptContent = document.createElement('script')
$scriptContent.src = './content.js'
$scriptContent.type = 'text/javascript'

document.body.appendChild($scriptSelection)
document.body.appendChild($scriptContent)
injectSaladictInternal()

ReactDOM.render(<WordPage area='notebook' />, document.getElementById('root'))
16 changes: 2 additions & 14 deletions src/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { message, storage } from '@/_helpers/browser-api'
import checkUpdate from '@/_helpers/check-update'
import { getDefaultSelectionInfo } from '@/_helpers/selection'
import { appConfigFactory, AppConfigMutable } from '@/app-config'
import { injectSaladictInternal } from '@/_helpers/injectSaladictInternal'

import i18nLoader from '@/_helpers/i18n'
import commonLocles from '@/_locales/common'
Expand All @@ -18,7 +19,7 @@ window.__SALADICT_INTERNAL_PAGE__ = true
window.__SALADICT_OPTIONS_PAGE__ = true
window.__SALADICT_LAST_SEARCH__ = ''

injectPanel()
injectSaladictInternal()

Vue.use(VueStash)
Vue.use(VueI18Next)
Expand Down Expand Up @@ -79,16 +80,3 @@ storage.sync.get('config')
},
})
})

function injectPanel () {
const $script = document.createElement('script')
$script.src = './content.js'
$script.type = 'text/javascript'

const $style = document.createElement('link')
$style.href = './content.css'
$style.rel = 'stylesheet'

document.body.appendChild($script)
document.body.appendChild($style)
}
4 changes: 4 additions & 0 deletions src/panel-internal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './panel-internal.scss'

const req = require['context']('@/components/dictionaries', true, /\.scss$/)
req.keys().forEach(req)
28 changes: 28 additions & 0 deletions src/panel-internal/panel-internal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.panel-StyleRoot {
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
font-weight: 700;
line-height: 1.6;
}

h1 {
font-size: 2em;
}

h2 {
font-size: 1.5em;
}

h3 {
font-size: 1.17em;
}

h4 {
font-size: 1em;
}

h5 {
font-size: 0.83em;
}

@import '../panel/panel';
}
28 changes: 1 addition & 27 deletions src/panel/panel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,11 @@
\*-----------------------------------------------*/
@import '../_sass_global/reset';

/*-----------------------------------------------*\
Base
\*-----------------------------------------------*/
html {
height: 100%;
box-sizing: border-box;
}

*, *:before, *:after {
box-sizing: inherit;
}

body {
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;
margin: 0;
padding: 0;
background-color: #fff;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica, Arial, "Hiragino Sans GB", "Hiragino Sans GB W3", "Microsoft YaHei UI", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}

/*-----------------------------------------------*\
Components
\*-----------------------------------------------*/
@import '../content/components/DictPanel/style';
@import '../content/components/MenuBar/style';
@import '../content/components/DictItem/style';

@import '../components/Speaker/style'
@import '../components/Speaker/style';
Loading

0 comments on commit 226be86

Please sign in to comment.