Skip to content

Commit

Permalink
Fix share dialog and make it into ShadowRoot
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Jun 14, 2019
1 parent 834a01e commit 3f56792
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 40 deletions.
2 changes: 1 addition & 1 deletion public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"message": "Maskbook decrypted content:"
},
"decrypted_postbox_add_decryptor": {
"message": "Add decryptor"
"message": "View / add receiver"
},
"decrypted_postbox_verified": {
"message": "Signature verified ✔"
Expand Down
2 changes: 1 addition & 1 deletion public/_locales/zh/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"message": "Maskbook 解密出的文本:"
},
"decrypted_postbox_add_decryptor": {
"message": "添加解密權限者:"
"message": "查看或添加可解密權限者"
},
"decrypted_postbox_verified": {
"message": "數字簽名驗證成功 ✔"
Expand Down
20 changes: 5 additions & 15 deletions src/components/InjectedComponents/DecryptedPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { PersonIdentifier } from '../../database/type'

interface DecryptPostSuccessProps {
data: { signatureVerifyResult: boolean; content: string }
displayAppendDecryptor: boolean
requestAppendDecryptor(to: Person[]): Promise<void>
alreadySelectedPreviously: Person[]
people: Person[]
Expand All @@ -32,11 +31,9 @@ function DecryptPostSuccess({ data, people, ...props }: DecryptPostSuccessProps)
{ShareMenu}
{geti18nString('decrypted_postbox_title')}
<Box flex={1} />
{props.displayAppendDecryptor ? (
<Link color="primary" onClick={showShare} className={classes.link}>
{geti18nString('decrypted_postbox_add_decryptor')}
</Link>
) : null}
<Link color="primary" onClick={showShare} className={classes.link}>
{geti18nString('decrypted_postbox_add_decryptor')}
</Link>
{data.signatureVerifyResult ? (
<span className={classes.pass}>{geti18nString('decrypted_postbox_verified')}</span>
) : (
Expand Down Expand Up @@ -72,14 +69,8 @@ interface DecryptPostProps {
alreadySelectedPreviously: Person[]
requestAppendDecryptor(to: Person[]): Promise<void>
}
function DecryptPost({
postBy,
whoAmI,
encryptedText,
people,
alreadySelectedPreviously,
requestAppendDecryptor,
}: DecryptPostProps) {
function DecryptPost(props: DecryptPostProps) {
const { postBy, whoAmI, encryptedText, people, alreadySelectedPreviously, requestAppendDecryptor } = props
const rAD = useCallback(
async (people: Person[]) => {
await requestAppendDecryptor(people)
Expand All @@ -102,7 +93,6 @@ function DecryptPost({
<DecryptPostSuccess
data={props.data}
alreadySelectedPreviously={alreadySelectedPreviously}
displayAppendDecryptor={whoAmI === postBy && alreadySelectedPreviously.length !== people.length}
requestAppendDecryptor={rAD}
people={people}
/>
Expand Down
9 changes: 8 additions & 1 deletion src/components/InjectedComponents/SelectPeopleDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { geti18nString } from '../../utils/i18n'
import { makeStyles } from '@material-ui/styles'
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, CircularProgress } from '@material-ui/core'
import { Person } from '../../database'
import { PortalShadowRoot } from '../../utils/jss/ShadowRootPortal'
interface Props {
open: boolean
people: Person[]
Expand Down Expand Up @@ -34,7 +35,13 @@ export function SelectPeopleDialog(props: Props) {
const canClose = !rejection && committed
const canCommit = committed || people.length === 0
return (
<Dialog onClose={canClose ? onClose : void 0} open={props.open} scroll="paper" fullWidth maxWidth="sm">
<Dialog
container={PortalShadowRoot}
onClose={canClose ? onClose : void 0}
open={props.open}
scroll="paper"
fullWidth
maxWidth="sm">
<DialogTitle className={classes.title}>{geti18nString('share_to')}</DialogTitle>
<DialogContent className={classes.content}>
<SelectPeopleUI
Expand Down
19 changes: 9 additions & 10 deletions src/extension/background-script/CryptoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { decodeText, encodeArrayBuffer, decodeArrayBuffer } from '../../utils/ty
import { constructAlpha40, deconstructPayload } from '../../utils/type-transform/Payload'
import { geti18nString } from '../../utils/i18n'
import { toCompressSecp256k1Point, unCompressSecp256k1Point } from '../../utils/type-transform/SECP256k1-Compression'
import { Person, getMyPrivateKeyAtFacebook } from '../../database'
import { Person, getMyPrivateKeyAtFacebook, queryPerson } from '../../database'
import {
getDefaultLocalKeyOrGenerateOneDB,
queryMyIdentityAtDB,
Expand All @@ -16,6 +16,7 @@ import {
PersonRecord,
} from '../../database/people'
import { PersonIdentifier } from '../../database/type'
import { gun } from '../../key-management/gun'

OnlyRunInContext('background', 'EncryptService')
//#region Encrypt & Decrypt
Expand Down Expand Up @@ -242,17 +243,15 @@ export async function verifyOthersProve(bio: string, others: PersonIdentifier) {
/**
* Get already shared target of the post
* @param postIdentifier Post identifier
* TODO: Rewrite this.
*/
export async function getSharedListOfPost(postIdentifier: string): Promise<Person[]> {
return []
// const post = await gun
// .get('posts')
// .get(postIdentifier)
// .once().then!()
// if (!post) return []
// delete post._
// return Promise.all(Object.keys(post).map(queryPerson))
const post = await gun
.get('posts')
.get(postIdentifier)
.once().then!()
if (!post) return []
delete post._
return Promise.all(Object.keys(post).map(id => queryPerson(new PersonIdentifier('facebook.com', id))))
}
export async function appendShareTarget(
postIdentifier: string,
Expand Down
2 changes: 1 addition & 1 deletion src/extension/content-script/injections/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function PostInspector(props: PostInspectorProps) {
const people = usePeople()
const [alreadySelectedPreviously, setAlreadySelectedPreviously] = useState<Person[]>([])
const { iv, ownersAESKeyEncrypted } = type.encryptedPost
if (whoAmI.userId === postBy.userId) {
if (whoAmI.equals(postBy)) {
useAsync(() => Services.Crypto.getSharedListOfPost(iv), [post]).then(p => setAlreadySelectedPreviously(p))
}
return (
Expand Down
13 changes: 4 additions & 9 deletions src/stories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { sleep } from '../utils/utils'
import { Button } from '@material-ui/core'
import { Person } from '../database'
import { PersonIdentifier } from '../database/type'
import { RenderInShadowRootWrapper } from '../utils/jss/renderInShadowRoot'

const demoPeople: Person[] = [
{
Expand Down Expand Up @@ -117,12 +118,7 @@ const FakePost: React.FC<{ title: string }> = props => (

storiesOf('Injections', module)
.add('Checkbox (unused)', () => <EncryptionCheckbox onCheck={action('Check')} />)
.add('AdditionalPostBox', () => (
<AdditionalPostBoxUI
people={demoPeople}
onRequestPost={action('onRequestPost')}
/>
))
.add('AdditionalPostBox', () => <AdditionalPostBoxUI people={demoPeople} onRequestPost={action('onRequestPost')} />)
.add('Additional Post Content', () => <AdditionalContent title="Additional Content" children="Content" />)
.add('SelectPeople', () => {
function SelectPeople() {
Expand All @@ -139,10 +135,10 @@ storiesOf('Injections', module)
boolean('Has frozen item?', true) ? [demoPeople[0]] : [],
)
return (
<>
<RenderInShadowRootWrapper>
{ShareMenu}
<Button onClick={showShare}>Show dialog</Button>
</>
</RenderInShadowRootWrapper>
)
}
return <SelectPeople />
Expand All @@ -162,7 +158,6 @@ storiesOf('Injections', module)
<FakePost title="Decrypted:">
<DecryptPostUI.success
alreadySelectedPreviously={[]}
displayAppendDecryptor={boolean('Post by myself?', true)}
requestAppendDecryptor={async () => {}}
people={demoPeople}
data={{ content: msg, signatureVerifyResult: vr }}
Expand Down
57 changes: 57 additions & 0 deletions src/utils/jss/ShadowRootPortal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { livingShadowRoots } from './ConstructableStyleSheetsRenderer'

const div = document.createElement('div')
document.body.appendChild(div)
export const PortalShadowRoot = (div.attachShadow({ mode: 'closed' }) as unknown) as any
livingShadowRoots.add(PortalShadowRoot as any)

Object.defineProperty(ShadowRoot.prototype, 'nodeType', {
get() {
if (this === PortalShadowRoot) return 1
else return Object.getOwnPropertyDescriptor(Node.prototype, 'nodeType')!.get!.call(this)
},
})
Object.defineProperty(ShadowRoot.prototype, 'tagName', {
get() {
if (this === PortalShadowRoot) return 'div'
else return undefined
},
})
Object.defineProperty(ShadowRoot.prototype, 'style', {
get() {
if (this === PortalShadowRoot) return div.style
else return undefined
},
})

{
// ? Hack for React, let event go through ShadowDom
const hackingEvents = new WeakMap<Event, EventTarget[]>()
function hack(eventName: string, shadowRoot: ShadowRoot) {
shadowRoot.addEventListener(eventName, (e: Event) => {
if (hackingEvents.has(e)) return
const path = e.composedPath()
// @ts-ignore
const e2 = new e.constructor(e.type, e)
hackingEvents.set(e2, path)
shadowRoot.dispatchEvent(e2)
e.stopPropagation()
e.stopImmediatePropagation()
})
}
// ? If react listen to some event, we also hack it.
document.addEventListener = new Proxy(document.addEventListener, {
apply(target, thisArg, args) {
const [eventName, listener, options] = args
hack(eventName, PortalShadowRoot)
return target.apply(thisArg, args)
},
})
const nativeTarget = Object.getOwnPropertyDescriptor(Event.prototype, 'target')!.get!
Object.defineProperty(Event.prototype, 'target', {
get() {
if (hackingEvents.has(this)) return hackingEvents.get(this)![0]
return nativeTarget.call(this)
},
})
}
4 changes: 2 additions & 2 deletions src/utils/jss/renderInShadowRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const jss = create({ ...jssPreset(), Renderer: ConstructableStyleSheetsRenderer
* @param shadow ShadowRoot that want to inject to
*/
export function renderInShadowRoot(node: React.ReactNode, shadow: ShadowRoot) {
ReactDOM.render(<Wrapper children={node} shadowRoot={shadow} />, shadow as any)
ReactDOM.render(<RenderInShadowRootWrapper children={node} />, shadow as any)
livingShadowRoots.add(shadow)
applyAdoptedStyleSheets()
return () => {
Expand All @@ -25,7 +25,7 @@ export function renderInShadowRoot(node: React.ReactNode, shadow: ShadowRoot) {
}

const generateClassName = createGenerateClassName()
class Wrapper extends React.PureComponent<{ shadowRoot: ShadowRoot }> {
export class RenderInShadowRootWrapper extends React.PureComponent {
state: { error?: Error } = { error: undefined }
render() {
if (this.state.error) return this.state.error.message
Expand Down

0 comments on commit 3f56792

Please sign in to comment.