From 9071439c12b45807b8b8d1067e9de93cb6b33070 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Thu, 23 Mar 2023 16:13:22 +0800 Subject: [PATCH] Adjust some layout stuff in composer --- src/components/compose.css | 17 +- src/components/compose.jsx | 1020 ++++++++++++++++++------------------ 2 files changed, 527 insertions(+), 510 deletions(-) diff --git a/src/components/compose.css b/src/components/compose.css index 62469c83..be7e038d 100644 --- a/src/components/compose.css +++ b/src/components/compose.css @@ -1,14 +1,18 @@ +#compose-container-outer { + width: 100%; + height: 100vh; + height: 100dvh; + overflow: auto; + align-self: flex-start; + padding: env(safe-area-inset-top) env(safe-area-inset-right) + env(safe-area-inset-bottom) env(safe-area-inset-left); +} #compose-container { + margin: auto; width: var(--main-width); max-width: 100vw; align-self: stretch; animation: fade-in 0.2s ease-out; - max-height: 100vh; - overflow: auto; -} -#compose-container.standalone { - max-height: none; - margin: auto; } #compose-container .compose-top { @@ -41,6 +45,7 @@ #compose-container textarea { font-size: 150%; font-size: calc(100% + 50% / var(--text-weight)); + max-height: 65vh; } } diff --git a/src/components/compose.jsx b/src/components/compose.jsx index 194e3312..8b45360b 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -498,182 +498,183 @@ function Compose({ }, [mediaAttachments]); return ( -
-
- {currentAccountInfo?.avatarStatic && ( - - )} - {!standalone ? ( - - {' '} - - - ) : ( - hasOpener && ( - {' '} + + + ) : ( + hasOpener && ( + - ) - )} -
- {!!replyToStatus && ( -
- -
- Replying to @ - {replyToStatus.account.acct || replyToStatus.account.username} - ’s status + onClose({ + fn: () => { + const passData = { + editStatus, + replyToStatus, + draftStatus: { + uid: UID.current, + status: textareaRef.current.value, + spoilerText: spoilerTextRef.current.value, + visibility, + language, + sensitive, + poll, + mediaAttachments, + }, + }; + window.opener.__COMPOSE__ = passData; // Pass it here instead of `showCompose` due to some weird proxy issue again + window.opener.__STATES__.showCompose = true; + }, + }); + }} + > + + + ) + )} +
+ {!!replyToStatus && ( +
+ +
+ Replying to @ + {replyToStatus.account.acct || replyToStatus.account.username} + ’s status +
-
- )} - {!!editStatus && ( -
- -
Editing source status
-
- )} -
{ - if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { - formRef.current.dispatchEvent( - new Event('submit', { cancelable: true }), - ); - } - }} - onSubmit={(e) => { - e.preventDefault(); + )} + {!!editStatus && ( +
+ +
Editing source status
+
+ )} + { + if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { + formRef.current.dispatchEvent( + new Event('submit', { cancelable: true }), + ); + } + }} + onSubmit={(e) => { + e.preventDefault(); - const formData = new FormData(e.target); - const entries = Object.fromEntries(formData.entries()); - console.log('ENTRIES', entries); - let { status, visibility, sensitive, spoilerText } = entries; + const formData = new FormData(e.target); + const entries = Object.fromEntries(formData.entries()); + console.log('ENTRIES', entries); + let { status, visibility, sensitive, spoilerText } = entries; - // Pre-cleanup - sensitive = sensitive === 'on'; // checkboxes return "on" if checked + // Pre-cleanup + sensitive = sensitive === 'on'; // checkboxes return "on" if checked - // Validation - /* Let the backend validate this + // Validation + /* Let the backend validate this if (stringLength(status) > maxCharacters) { alert(`Status is too long! Max characters: ${maxCharacters}`); return; @@ -688,252 +689,170 @@ function Compose({ return; } */ - if (poll) { - if (poll.options.length < 2) { - alert('Poll must have at least 2 options'); - return; + if (poll) { + if (poll.options.length < 2) { + alert('Poll must have at least 2 options'); + return; + } + if (poll.options.some((option) => option === '')) { + alert('Some poll choices are empty'); + return; + } } - if (poll.options.some((option) => option === '')) { - alert('Some poll choices are empty'); - return; + // TODO: check for URLs and use `charactersReservedPerUrl` to calculate max characters + + if (mediaAttachments.length > 0) { + // If there are media attachments, check if they have no descriptions + const hasNoDescriptions = mediaAttachments.some( + (media) => !media.description?.trim?.(), + ); + if (hasNoDescriptions) { + const yes = confirm( + 'Some media have no descriptions. Continue?', + ); + if (!yes) return; + } } - } - // TODO: check for URLs and use `charactersReservedPerUrl` to calculate max characters - if (mediaAttachments.length > 0) { - // If there are media attachments, check if they have no descriptions - const hasNoDescriptions = mediaAttachments.some( - (media) => !media.description?.trim?.(), - ); - if (hasNoDescriptions) { - const yes = confirm('Some media have no descriptions. Continue?'); - if (!yes) return; - } - } + // Post-cleanup + spoilerText = (sensitive && spoilerText) || undefined; + status = status === '' ? undefined : status; - // Post-cleanup - spoilerText = (sensitive && spoilerText) || undefined; - status = status === '' ? undefined : status; - - setUIState('loading'); - (async () => { - try { - console.log('MEDIA ATTACHMENTS', mediaAttachments); - if (mediaAttachments.length > 0) { - // Upload media attachments first - const mediaPromises = mediaAttachments.map((attachment) => { - const { file, description, id } = attachment; - console.log('UPLOADING', attachment); - if (id) { - // If already uploaded - return attachment; - } else { - const params = removeNullUndefined({ - file, - description, - }); - return masto.v2.mediaAttachments - .create(params) - .then((res) => { - if (res.id) { - attachment.id = res.id; - } - return res; + setUIState('loading'); + (async () => { + try { + console.log('MEDIA ATTACHMENTS', mediaAttachments); + if (mediaAttachments.length > 0) { + // Upload media attachments first + const mediaPromises = mediaAttachments.map((attachment) => { + const { file, description, id } = attachment; + console.log('UPLOADING', attachment); + if (id) { + // If already uploaded + return attachment; + } else { + const params = removeNullUndefined({ + file, + description, }); - } - }); - const results = await Promise.allSettled(mediaPromises); - - // If any failed, return - if ( - results.some((result) => { - return result.status === 'rejected' || !result.value?.id; - }) - ) { - setUIState('error'); - // Alert all the reasons - results.forEach((result) => { - if (result.status === 'rejected') { - console.error(result); - alert(result.reason || `Attachment #${i} failed`); + return masto.v2.mediaAttachments + .create(params) + .then((res) => { + if (res.id) { + attachment.id = res.id; + } + return res; + }); } }); - return; + const results = await Promise.allSettled(mediaPromises); + + // If any failed, return + if ( + results.some((result) => { + return result.status === 'rejected' || !result.value?.id; + }) + ) { + setUIState('error'); + // Alert all the reasons + results.forEach((result) => { + if (result.status === 'rejected') { + console.error(result); + alert(result.reason || `Attachment #${i} failed`); + } + }); + return; + } + + console.log({ results, mediaAttachments }); } - console.log({ results, mediaAttachments }); - } - - /* NOTE: + /* NOTE: Using snakecase here because masto.js's `isObject` returns false for `params`, ONLY happens when opening in pop-out window. This is maybe due to `window.masto` variable being passed from the parent window. The check that failed is `x.constructor === Object`, so maybe the `Object` in new window is different than parent window's? Code: https://github.com/neet/masto.js/blob/dd0d649067b6a2b6e60fbb0a96597c373a255b00/src/serializers/is-object.ts#L2 */ - let params = { - status, - // spoilerText, - spoiler_text: spoilerText, - language, - sensitive, - poll, - // mediaIds: mediaAttachments.map((attachment) => attachment.id), - media_ids: mediaAttachments.map((attachment) => attachment.id), - }; - if (editStatus && supports('@mastodon/edit-media-attributes')) { - params.media_attributes = mediaAttachments.map((attachment) => { - return { - id: attachment.id, - description: attachment.description, - // focus - // thumbnail - }; - }); - } else if (!editStatus) { - params.visibility = visibility; - // params.inReplyToId = replyToStatus?.id || undefined; - params.in_reply_to_id = replyToStatus?.id || undefined; - } - params = removeNullUndefined(params); - console.log('POST', params); - - let newStatus; - if (editStatus) { - newStatus = await masto.v1.statuses.update( - editStatus.id, - params, - ); - saveStatus(newStatus, instance, { - skipThreading: true, - }); - } else { - newStatus = await masto.v1.statuses.create(params, { - idempotencyKey: UID.current, - }); - } - setUIState('default'); - - // Close - onClose({ - newStatus, - instance, - }); - } catch (e) { - console.error(e); - alert(e?.reason || e); - setUIState('error'); - } - })(); - }} - > -
- { - updateCharCount(); - }} - /> -