11import React from 'react'
22import { render } from 'react-dom'
3+ // @ts -ignore
4+ import smoothScrollPolyfill from 'smoothscroll-polyfill'
5+ import * as rangy from 'rangy'
6+ // @ts -ignore
7+ import 'rangy/lib/rangy-classapplier'
8+ import 'rangy/lib/rangy-highlighter'
39
410import logger from '../../common/logger'
511import { SupportLanguages } from '../../common/types'
612import translationStack from './common/translation-stack'
713import { TextSelection } from './common/types'
14+ import { getFirstRange } from './common/utils'
815import App from './components/App'
916import './styles/index.scss'
1017import { TranslateJobsProvider } from './providers/translate-jobs'
1118
1219let isAppAttached = false
13- let lastSelection : TextSelection | undefined
20+ let lastSelection : ( TextSelection & { selection : RangySelection } ) | undefined
21+ let highlighter : any
22+
1423const main = async ( ) => {
1524 const container = document . createElement ( 'div' )
1625 container . id = 'ate-container'
@@ -28,26 +37,43 @@ const main = async () => {
2837
2938 window . addEventListener ( 'load' , ( ) => {
3039 try {
31- document . querySelector ( 'body' ) ?. append ( iconContainer )
32- document . querySelector ( 'body' ) ?. append ( container )
40+ // @ts -ignore
41+ rangy . init ( )
42+ // @ts -ignore
43+ highlighter = rangy . createHighlighter ( )
44+ // @ts -ignore
45+ highlighter . addClassApplier (
46+ // @ts -ignore
47+ rangy . createClassApplier ( 'ate-highlight' , {
48+ ignoreWhiteSpace : true ,
49+ tagNames : [ 'span' , 'a' ] ,
50+ } ) ,
51+ )
52+
53+ document . querySelector < HTMLBodyElement > ( 'body' ) ?. append ( iconContainer )
54+ document . querySelector < HTMLBodyElement > ( 'body' ) ?. append ( container )
3355
3456 attachListeners ( )
3557
3658 // TODO: remove before deploying
37- initApp ( )
59+ // initApp()
3860 } catch ( err ) {
3961 logger . error ( {
4062 err,
4163 } )
4264 }
4365 } )
66+
67+ if ( ! ( 'scrollBehavior' in document . documentElement . style ) ) {
68+ smoothScrollPolyfill . polyfill ( )
69+ }
4470}
4571
4672const onMouseUp = ( e : MouseEvent ) => {
47- const selection = window . getSelection ( )
73+ const selection = rangy . getSelection ( )
4874 const iconElement = document . querySelector < HTMLSpanElement > ( '#ate-icon' )
4975
50- if ( selection ? .toString ( ) . trim ( ) && iconElement ) {
76+ if ( selection . toString ( ) . trim ( ) && iconElement ) {
5177 lastSelection = getTextSelection ( selection )
5278 iconElement . style . top = e . pageY + 20 + 'px'
5379 iconElement . style . left = e . pageX + 'px'
@@ -73,24 +99,49 @@ const onClickTranslate = (selection: TextSelection) => {
7399
74100const attachListeners = ( ) => {
75101 document . addEventListener ( 'mouseup' , onMouseUp , false )
76- document . querySelector ( '#ate-icon' ) ?. addEventListener ( 'click' , ( e ) => {
77- logger . debug ( {
78- msg : 'lastSelection' ,
79- lastSelection,
102+ document
103+ . querySelector < HTMLSpanElement > ( '#ate-icon' )
104+ ?. addEventListener ( 'click' , function ( ) {
105+ logger . debug ( {
106+ msg : 'lastSelection' ,
107+ lastSelection,
108+ } )
109+
110+ if ( lastSelection ) {
111+ highlightSelection ( lastSelection . selection )
112+
113+ onClickTranslate ( {
114+ text : lastSelection . text ,
115+ parentElement : lastSelection . parentElement ,
116+ sourceLang : lastSelection . sourceLang ,
117+ } )
118+
119+ setTimeout ( ( ) => {
120+ lastSelection ?. selection . removeAllRanges ( )
121+ this . classList . remove ( 'active' )
122+ } , 0 )
123+ }
80124 } )
81- if ( lastSelection ) {
82- onClickTranslate ( lastSelection )
83- }
84- } )
85125}
86126
87- const getTextSelection = ( selection : Selection ) : TextSelection => {
127+ const highlightSelection = ( selection : RangySelection ) => {
128+ const range = getFirstRange ( selection )
129+
130+ if ( ! range || ! highlighter ) {
131+ return
132+ }
133+
134+ highlighter . highlightSelection ( 'ate-highlight' )
135+ }
136+
137+ const getTextSelection = (
138+ selection : RangySelection ,
139+ ) : TextSelection & { selection : RangySelection } => {
88140 const text = selection . toString ( ) . trim ( )
89141
90142 return {
91- anchor : selection . anchorNode ?. parentElement ?? undefined ,
92- anchorOffset : selection . anchorOffset ,
93- rangeCount : selection . rangeCount ,
143+ selection,
144+ parentElement : selection . anchorNode ?. parentElement ?? undefined ,
94145 sourceLang : getSourceLang ( ) ,
95146 text,
96147 }
0 commit comments