Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ let openOnInitAnswered = false
export function Composition({ type = 'timeline', requireClipboardPermission }: PostDialogProps) {
const { t } = useI18N()

const [reason, setReason] = useState<'timeline' | 'popup' | 'reply'>('timeline')
// #region Open
const [open, setOpen] = useState(false)
const onClose = useCallback(() => {
Expand Down Expand Up @@ -45,8 +46,9 @@ export function Composition({ type = 'timeline', requireClipboardPermission }: P

useEffect(() => {
return MaskMessages.events.requestComposition.on(({ reason, open, content, options }) => {
if (reason !== type || globalUIState.profiles.value.length <= 0) return
if (reason !== 'reply' && (reason !== type || globalUIState.profiles.value.length <= 0)) return
setOpen(open)
setReason(reason)
if (content) UI.current?.setMessage(content)
if (options?.target) UI.current?.setEncryptionKind(options.target)
if (options?.startupPlugin) UI.current?.startPlugin(options.startupPlugin)
Expand All @@ -63,11 +65,10 @@ export function Composition({ type = 'timeline', requireClipboardPermission }: P
// #endregion

// #region submit
const onSubmit_ = useSubmit(onClose)
const onSubmit_ = useSubmit(onClose, reason)
// #endregion

const UI = useRef<CompositionRef>(null)

const networkSupport = activatedSocialNetworkUI.injection.newPostComposition?.supportedOutputTypes
return (
<DialogStackingProvider>
Expand Down
20 changes: 14 additions & 6 deletions packages/mask/src/components/CompositionDialog/useSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { unreachable } from '@dimensiondev/kit'
import { useLastRecognizedIdentity } from '../DataSource/useActivatedUI'
import { isFacebook } from '../../social-network-adaptor/facebook.com/base'

export function useSubmit(onClose: () => void) {
export function useSubmit(onClose: () => void, reason: 'timeline' | 'popup' | 'reply') {
const { t } = useI18N()
const whoAmI = useLastRecognizedIdentity()

Expand Down Expand Up @@ -45,32 +45,40 @@ export function useSubmit(onClose: () => void) {
random: new Date().toLocaleString(),
})
if (redPacketMetadata.ok) {
await pasteImage(redPacketPreText.replace(encrypted, '') ?? defaultText, encrypted, 'eth')
await pasteImage(redPacketPreText.replace(encrypted, '') ?? defaultText, encrypted, 'eth', reason)
} else {
await pasteImage(defaultText, encrypted, 'v2')
await pasteImage(defaultText, encrypted, 'v2', reason)
}
} else {
pasteTextEncode(
(redPacketMetadata.ok ? redPacketPreText : null) ??
t('additional_post_box__encrypted_post_pre', { encrypted }),
reason,
)
}
onClose()
},
[t, whoAmI, onClose],
[t, whoAmI, onClose, reason],
)
}

function pasteTextEncode(text: string) {
function pasteTextEncode(text: string, reason: 'timeline' | 'popup' | 'reply') {
activatedSocialNetworkUI.automation.nativeCompositionDialog?.appendText?.(text, {
recover: true,
reason,
})
}
async function pasteImage(relatedTextPayload: string, encrypted: string, template: ImageTemplateTypes) {
async function pasteImage(
relatedTextPayload: string,
encrypted: string,
template: ImageTemplateTypes,
reason: 'timeline' | 'popup' | 'reply',
) {
const img = await SteganographyTextPayload(template, encrypted)
// Don't await this, otherwise the dialog won't disappear
activatedSocialNetworkUI.automation.nativeCompositionDialog!.attachImage!(img, {
recover: true,
relatedTextPayload,
reason,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface PostDialogHintUIProps extends withClasses<'buttonTransform' | '
const useStyles = makeStyles()((theme) => ({
button: {
// TODO: is it correct? (what about twitter?)
padding: isMobileFacebook ? 0 : '8px',
padding: isMobileFacebook ? 0 : '7px',
},
text: {
fontSize: 14,
Expand All @@ -40,6 +40,9 @@ const useStyles = makeStyles()((theme) => ({
padding: '8px 10px',
borderBottom: '1px solid #dadde1',
},
tooltip: {
color: 'white',
},
}))

const EntryIconButton = memo((props: PostDialogHintUIProps) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { abortSignalTimeout, delay } from '@dimensiondev/kit'
import { inputText, pasteText } from '@masknet/injected-script'
import { postEditorDraftContentSelector, newPostButtonSelector } from '../utils/selector'
import { newPostButtonSelector, postEditorDraftContentSelector } from '../utils/selector'
import type { SocialNetworkUI } from '../../../social-network'
import { getEditorContent, hasFocus, isCompose, hasEditor } from '../utils/postBox'
import { getEditorContent, hasEditor, hasFocus, isCompose } from '../utils/postBox'
import { untilElementAvailable } from '../../../utils/dom'
import { isMobileTwitter } from '../utils/isMobile'
import { MaskMessages } from '../../../utils/messages'
Expand All @@ -19,7 +19,8 @@ export const pasteTextToCompositionTwitter: SocialNetworkUI.AutomationCapabiliti
const checkSignal = () => {
if (abort.aborted) throw new Error('Aborted')
}
if (!isCompose() && !hasEditor()) {

if (!isCompose() && !hasEditor() && opt?.reason !== 'reply') {
// open tweet window
await untilElementAvailable(newPostButtonSelector())
newPostButtonSelector().evaluate()!.click()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MutationObserverWatcher, LiveSelector } from '@dimensiondev/holoflows-kit'
import { createReactRootShadowed } from '../../../utils/shadow-root/renderInShadowRoot'
import { Composition } from '../../../components/CompositionDialog/Composition'
import { postEditorContentInPopupSelector, rootSelector } from '../utils/selector'
import { startWatch } from '../../../utils/watcher'
import { postEditorContentInPopupSelector, rootSelector } from '../utils/selector'

function renderPostDialogTo<T>(reason: 'timeline' | 'popup', ls: LiveSelector<T, true>, signal: AbortSignal) {
const watcher = new MutationObserverWatcher(ls)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { MutationObserverWatcher, LiveSelector } from '@dimensiondev/holoflows-kit'
import { postEditorInTimelineSelector, postEditorInPopupSelector } from '../utils/selector'
import { isReplyPageSelector, postEditorInPopupSelector, searchReplyToolbarSelector } from '../utils/selector'
import { createReactRootShadowed } from '../../../utils/shadow-root/renderInShadowRoot'
import { PostDialogHint } from '../../../components/InjectedComponents/PostDialogHint'
import { MaskMessages } from '../../../utils/messages'
Expand Down Expand Up @@ -29,7 +29,8 @@ const useStyles = makeStyles()((theme) => ({

export function injectPostDialogHintAtTwitter(signal: AbortSignal) {
const emptyNode = document.createElement('div')
renderPostDialogHintTo('timeline', postEditorInTimelineSelector(), signal)
renderPostDialogHintTo('timeline', searchReplyToolbarSelector(), signal)

renderPostDialogHintTo(
'popup',
postEditorInPopupSelector().map((x) => (isCompose() && hasEditor() ? x : emptyNode)),
Expand All @@ -49,20 +50,32 @@ function renderPostDialogHintTo<T>(reason: 'timeline' | 'popup', ls: LiveSelecto
function PostDialogHintAtTwitter({ reason }: { reason: 'timeline' | 'popup' }) {
const { classes } = useStyles()
const { t } = useI18N()
const [isReply, setIsReply] = useState(false)

const onHintButtonClicked = useCallback(() => {
const content = sayHelloShowed[twitterBase.networkIdentifier].value
? undefined
: makeTypedMessageText(
t('setup_guide_say_hello_content') +
t('setup_guide_say_hello_follow', { account: '@realMaskNetwork' }),
)
MaskMessages.events.requestComposition.sendToLocal({ reason, open: true, content })

MaskMessages.events.requestComposition.sendToLocal({
reason: isReplyPageSelector() ? 'reply' : reason,
open: true,
content,
})
sayHelloShowed[twitterBase.networkIdentifier].value = true
}, [reason])
}, [reason, isReplyPageSelector])

useEffect(() => {
setIsReply(isReplyPageSelector())
}, [location])

return (
<PostDialogHint
classes={{ iconButton: classes.iconButton, tooltip: classes.tooltip }}
size={17}
size={20}
onHintButtonClicked={onHintButtonClicked}
tooltip={{ disabled: false }}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,17 @@ export const sideBarProfileSelector: () => LiveSelector<E, true> = () =>
querySelector<E>('[role="banner"] [role="navigation"] [aria-label="Lists"] > div')
export const postEditorInTimelineSelector: () => LiveSelector<E, true> = () =>
querySelector<E>('[role="main"] :not(aside) > [role="progressbar"] ~ div [role="button"][aria-label]:nth-child(6)')

export const isReplyPageSelector = () => !!location.pathname.match(/^\/\w+\/status\/\d+$/)
export const postEditorDraftContentSelector = () => {
if (location.pathname === '/compose/tweet') {
return querySelector<HTMLDivElement>(
'[contenteditable][aria-label][spellcheck],textarea[aria-label][spellcheck]',
)
}
if (isReplyPageSelector()) {
return querySelector<HTMLElement>('div[data-testid="tweetTextarea_0"]')
}
return (isCompose() ? postEditorInPopupSelector() : postEditorInTimelineSelector()).querySelector<HTMLElement>(
'.public-DraftEditor-content, [contenteditable][aria-label][spellcheck]',
)
Expand Down Expand Up @@ -264,3 +269,11 @@ export const searchTwitterAvatarNFTSelector = () =>
querySelector<E>('a[href$="/nft"]').closest<E>(1).querySelector('a div:nth-child(3) > div')

export const searchTwitterAvatarNFTLinkSelector = () => querySelector<E>('a[href$="/nft"]')

export const searchReplyToolbarSelector = () =>
querySelector<E>('div[data-testid="primaryColumn"] div[data-testid="toolBar"]').querySelector<E>(
'div[data-testid="geoButton"]',
)

export const searchRejectReplyTextSelector = () =>
querySelector<E>('div[data-testid="tweetTextarea_0"] > div > div > div > span')
2 changes: 2 additions & 0 deletions packages/mask/src/social-network/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,11 @@ export namespace SocialNetworkUI {
export interface NativeCompositionAttachImageOptions {
recover?: boolean
relatedTextPayload?: string
reason?: 'timeline' | 'popup' | 'reply'
}
export interface NativeCompositionAttachTextOptions {
recover?: boolean
reason?: 'timeline' | 'popup' | 'reply'
}
export interface MaskCompositionDialog {
open?(content: SerializableTypedMessages, options?: MaskCompositionDialogOpenOptions): void
Expand Down
2 changes: 1 addition & 1 deletion packages/shared-base/src/Messages/Mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export interface UpdateEvent<Data> {
}

export interface CompositionRequest {
readonly reason: 'timeline' | 'popup'
readonly reason: 'timeline' | 'popup' | 'reply'
readonly open: boolean
readonly content?: SerializableTypedMessages
readonly options?: {
Expand Down