11import { keyToCss } from '../../utils/css_map.js' ;
22import { dom } from '../../utils/dom.js' ;
33import { inject } from '../../utils/inject.js' ;
4- import { showErrorModal } from '../../utils/modals.js' ;
4+ import { hideModal , modalCancelButton , showErrorModal , showModal } from '../../utils/modals.js' ;
55import { buildStyle , notificationSelector } from '../../utils/interface.js' ;
66import { pageModifications } from '../../utils/mutations.js' ;
77import { notify } from '../../utils/notifications.js' ;
@@ -14,7 +14,8 @@ import { timelineObject } from '../../utils/react_props.js';
1414
1515const storageKey = 'quote_replies.draftLocation' ;
1616const buttonClass = 'xkit-quote-replies' ;
17- const meatballButtonId = 'quote-replies' ;
17+ const newPostMeatballButtonId = 'quote-replies-new-post' ;
18+ const reblogMeatballButtonId = 'quote-replies-reblog' ;
1819const dropdownButtonClass = 'xkit-quote-replies-dropdown' ;
1920
2021export const styleElement = buildStyle ( `
@@ -67,6 +68,7 @@ const activitySelector = `:is(${keyToCss('notification')} > ${keyToCss('activity
6768
6869const dropdownSelector = '[role="tabpanel"] *' ;
6970
71+ let defaultMode ;
7072let originalPostTag ;
7173let tagReplyingBlog ;
7274let newTab ;
@@ -150,6 +152,7 @@ const createGenericActivityReplyPost = async (notificationProps) => {
150152 ...tagReplyingBlog ? [ replyingBlog . name ] : [ ]
151153 ] . join ( ',' ) ;
152154
155+ // never a reblog (always a new post)
153156 return { content, tags } ;
154157} ;
155158
@@ -169,10 +172,62 @@ const createActivityReplyPost = async ({ type, timestamp, targetPostId, targetTu
169172 const { content : replyContent , blog : { name : replyingBlogName , uuid : replyingBlogUuid } } = reply ;
170173 const targetPostUrl = `https://${ targetTumblelogName } .tumblr.com/post/${ targetPostId } ` ;
171174
172- return createReplyPost ( { type, replyingBlogName, replyingBlogUuid, targetPostSummary, targetPostUrl, replyContent } ) ;
175+ const tryToReblog = defaultMode === 'reblog' ;
176+ return createReplyPost ( { type, replyingBlogName, replyingBlogUuid, targetPostSummary, targetPostUrl, replyContent, targetTumblelogName, targetPostId, tryToReblog } ) ;
173177} ;
174178
175- const createReplyPost = ( { type, replyingBlogName, replyingBlogUuid, targetPostSummary, targetPostUrl, replyContent } ) => {
179+ const getReblogData = async ( { targetTumblelogName, targetPostId } ) => {
180+ try {
181+ const { blog, canReblog, id : parentPostId , blog : { uuid : parentTumblelogUUID } , reblogKey } = await apiFetch ( `/v2/blog/${ targetTumblelogName } /posts/${ targetPostId } ` ) . then ( ( { response } ) => response ) ;
182+ if ( canReblog !== false && ! blog ?. isPasswordProtected ) {
183+ return { parentPostId, parentTumblelogUUID, reblogKey } ;
184+ }
185+ } catch { }
186+ return new Promise ( resolve =>
187+ showModal ( {
188+ title : 'Cannot reblog' ,
189+ message : [ 'The target post cannot be reblogged!' ] ,
190+ buttons : [
191+ modalCancelButton ,
192+ dom ( 'button' , { class : 'blue' } , {
193+ click ( ) {
194+ hideModal ( ) ;
195+ resolve ( false ) ;
196+ }
197+ } , [ 'Reply in a new post' ] )
198+ ]
199+ } )
200+ ) ;
201+ } ;
202+
203+ const createReplyPost = async ( { type, replyingBlogName, replyingBlogUuid, targetPostSummary, targetPostUrl, replyContent, targetTumblelogName, targetPostId, tryToReblog } ) => {
204+ const reblogData = tryToReblog && await getReblogData ( { targetTumblelogName, targetPostId } ) ;
205+ if ( reblogData ) {
206+ const { parentPostId, parentTumblelogUUID, reblogKey } = reblogData ;
207+
208+ const text = `@${ replyingBlogName } replied:` ;
209+ const formatting = [
210+ { start : 0 , end : replyingBlogName . length + 1 , type : 'mention' , blog : { uuid : replyingBlogUuid } }
211+ ] ;
212+
213+ const content = [
214+ { type : 'text' , text, formatting } ,
215+ Object . assign ( replyContent [ 0 ] , { subtype : 'indented' } ) ,
216+ { type : 'text' , text : '\u200B' }
217+ ] ;
218+ const tags = [
219+ ...tagReplyingBlog ? [ replyingBlogName ] : [ ]
220+ ] . join ( ',' ) ;
221+
222+ return {
223+ content,
224+ tags,
225+ parent_post_id : parentPostId ,
226+ parent_tumblelog_uuid : parentTumblelogUUID ,
227+ reblog_key : reblogKey
228+ } ;
229+ }
230+
176231 const verbiage = {
177232 reply : 'replied to your post' ,
178233 reply_to_comment : 'replied to you in a post' ,
@@ -234,7 +289,7 @@ const determineNoteReplyType = ({ noteProps, parentNoteProps }) => {
234289 return false ;
235290} ;
236291
237- const quoteNoteReply = async ( { currentTarget } ) => {
292+ const quoteNoteReply = async ( { currentTarget } , tryToReblog ) => {
238293 const {
239294 noteProps : {
240295 note : { blogName : replyingBlogName , content : replyContent }
@@ -243,11 +298,16 @@ const quoteNoteReply = async ({ currentTarget }) => {
243298
244299 const { type, targetBlogName } = determineNoteReplyType ( currentTarget . __notePropsData ) ;
245300
246- const { summary : targetPostSummary , postUrl : targetPostUrl } = await timelineObject ( currentTarget . closest ( keyToCss ( 'meatballMenu' ) ) ) ;
301+ const {
302+ summary : targetPostSummary ,
303+ postUrl : targetPostUrl ,
304+ blogName : targetTumblelogName ,
305+ id : targetPostId
306+ } = await timelineObject ( currentTarget . closest ( keyToCss ( 'meatballMenu' ) ) ) ;
247307 const replyingBlogUuid = await apiFetch ( `/v2/blog/${ replyingBlogName } /info?fields[blogs]=uuid` )
248308 . then ( ( { response : { blog : { uuid } } } ) => uuid ) ;
249309
250- const replyPost = createReplyPost ( { type, replyingBlogName, replyingBlogUuid, targetPostSummary, targetPostUrl, replyContent } ) ;
310+ const replyPost = await createReplyPost ( { type, replyingBlogName, replyingBlogUuid, targetPostSummary, targetPostUrl, replyContent, targetTumblelogName , targetPostId , tryToReblog } ) ;
251311 openQuoteReplyDraft ( targetBlogName , replyPost ) ;
252312} ;
253313
@@ -273,15 +333,22 @@ const openQuoteReplyDraft = async (tumblelogName, replyPost) => {
273333
274334export const main = async function ( ) {
275335 ( { [ originalPostTagStorageKey ] : originalPostTag } = await browser . storage . local . get ( originalPostTagStorageKey ) ) ;
276- ( { tagReplyingBlog, newTab } = await getPreferences ( 'quote_replies' ) ) ;
336+ ( { defaultMode , tagReplyingBlog, newTab } = await getPreferences ( 'quote_replies' ) ) ;
277337
278338 pageModifications . register ( notificationSelector , processNotifications ) ;
279339
280340 registerReplyMeatballItem ( {
281- id : meatballButtonId ,
282- label : 'Quote this reply' ,
341+ id : defaultMode === 'reblog' ? reblogMeatballButtonId : newPostMeatballButtonId ,
342+ label : `Quote this reply (${ defaultMode === 'reblog' ? 'as reblog' : 'as new post' } )` ,
343+ notePropsFilter : notePropsData => Boolean ( determineNoteReplyType ( notePropsData ) ) ,
344+ onclick : event => quoteNoteReply ( event , defaultMode === 'reblog' ) . catch ( showErrorModal )
345+ } ) ;
346+
347+ registerReplyMeatballItem ( {
348+ id : defaultMode !== 'reblog' ? reblogMeatballButtonId : newPostMeatballButtonId ,
349+ label : `Quote this reply (${ defaultMode !== 'reblog' ? 'as reblog' : 'as new post' } )` ,
283350 notePropsFilter : notePropsData => Boolean ( determineNoteReplyType ( notePropsData ) ) ,
284- onclick : event => quoteNoteReply ( event ) . catch ( showErrorModal )
351+ onclick : event => quoteNoteReply ( event , defaultMode !== 'reblog' ) . catch ( showErrorModal )
285352 } ) ;
286353
287354 const { [ storageKey ] : draftLocation } = await browser . storage . local . get ( storageKey ) ;
@@ -294,7 +361,8 @@ export const main = async function () {
294361
295362export const clean = async function ( ) {
296363 pageModifications . unregister ( processNotifications ) ;
297- unregisterReplyMeatballItem ( meatballButtonId ) ;
364+ unregisterReplyMeatballItem ( newPostMeatballButtonId ) ;
365+ unregisterReplyMeatballItem ( reblogMeatballButtonId ) ;
298366
299367 $ ( `.${ buttonClass } ` ) . remove ( ) ;
300368} ;
@@ -305,6 +373,6 @@ export const onStorageChanged = async function (changes) {
305373 }
306374
307375 if ( Object . keys ( changes ) . some ( key => key . startsWith ( 'quote_replies.preferences' ) ) ) {
308- ( { tagReplyingBlog , newTab } = await getPreferences ( 'quote_replies' ) ) ;
376+ clean ( ) . then ( main ) ;
309377 }
310378} ;
0 commit comments