diff --git a/src/api/posts.ts b/src/api/posts.ts index 520307f..212c861 100644 --- a/src/api/posts.ts +++ b/src/api/posts.ts @@ -1,6 +1,6 @@ import { BACKEND_URL } from "@/constants" import { PAGE_SIZE, http } from "./common" -import { Profile } from "./users" +import { defaultProfile, Profile } from "./users" export interface Attachment { id: string; @@ -155,6 +155,45 @@ export async function getPostContext( return data } +export async function previewPost( + authToken: string, + content: string, +): Promise { + const url = `${BACKEND_URL}/api/v1/statuses/preview` + const response = await http(url, { + method: "POST", + json: { + status: content, + content_type: "text/markdown", + }, + authToken, + }) + const data = await response.json() + return { + id: "", + uri: "", + created_at: "", + edited_at: null, + account: defaultProfile(), + content: data.content, + in_reply_to_id: null, + reblog: null, + visibility: Visibility.Public, + replies_count: 0, + favourites_count: 0, + reblogs_count: 0, + media_attachments: [], + mentions: [], + tags: [], + favourited: false, + reblogged: false, + ipfs_cid: null, + token_id: null, + token_tx_id: null, + links: [], + } +} + export interface PostData { content: string; in_reply_to_id: string | null; diff --git a/src/api/users.ts b/src/api/users.ts index c0f4e8a..587cfae 100644 --- a/src/api/users.ts +++ b/src/api/users.ts @@ -44,7 +44,7 @@ export interface Profile { statuses_count: number; } -export function guest(): Profile { +export function defaultProfile(): Profile { return { id: "", username: "", diff --git a/src/assets/feather/eye-off.svg b/src/assets/feather/eye-off.svg new file mode 100644 index 0000000..b46c58f --- /dev/null +++ b/src/assets/feather/eye-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/feather/eye.svg b/src/assets/feather/eye.svg new file mode 100644 index 0000000..7298aef --- /dev/null +++ b/src/assets/feather/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/PostEditor.vue b/src/components/PostEditor.vue index ccc7ebc..b5fa8af 100644 --- a/src/components/PostEditor.vue +++ b/src/components/PostEditor.vue @@ -11,12 +11,18 @@ +
+
+
{{ getCharacterCount() }}
@@ -106,16 +123,18 @@ import { nextTick, onMounted } from "vue" import { $, $computed, $ref } from "vue/macros" import { - Visibility, - VISIBILITY_MAP, + createPost, + previewPost, + uploadAttachment, + Attachment, Mention, Post, - createPost, - Attachment, - uploadAttachment, + Visibility, + VISIBILITY_MAP, } from "@/api/posts" import { User } from "@/api/users" import Avatar from "@/components/Avatar.vue" +import PostContent from "@/components/PostContent.vue" import VisibilityIcon from "@/components/VisibilityIcon.vue" import { useInstanceInfo } from "@/store/instance" import { useCurrentUser } from "@/store/user" @@ -147,6 +166,7 @@ let attachments = $ref([]) let visibility = $ref(Visibility.Public) let visibilityMenuVisible = $ref(false) +let preview = $ref(null) let isLoading = $ref(false) let errorMessage = $ref(null) @@ -173,6 +193,7 @@ if (props.inReplyTo && props.inReplyTo.visibility !== Visibility.Public) { onMounted(() => { if (postFormContentRef) { setupAutoResize(postFormContentRef) + triggerResize(postFormContentRef) } }) @@ -236,6 +257,18 @@ function getCharacterCount(): number { return (instance.post_character_limit - content.length) } +function canPreview(): boolean { + return content.length > 0 +} + +async function togglePreview() { + if (preview === null) { + preview = await previewPost(ensureAuthToken(), content) + } else { + preview = null + } +} + function canPublish(): boolean { return getCharacterCount() >= 0 && !isLoading } @@ -266,6 +299,7 @@ async function publish() { removeLocalDraft() content = "" attachments = [] + preview = null if (postFormContentRef) { await nextTick() triggerResize(postFormContentRef) @@ -350,9 +384,12 @@ $line-height: 1.5; gap: calc($block-inner-padding / 2); padding: calc($block-inner-padding / 1.5) $block-inner-padding; + .toolbar-space { + flex-grow: 1; + } + .character-counter { font-weight: bold; - margin-left: auto; } .submit-btn-small { diff --git a/src/components/SubscriptionEthereum.vue b/src/components/SubscriptionEthereum.vue index 9983f68..23055bf 100644 --- a/src/components/SubscriptionEthereum.vue +++ b/src/components/SubscriptionEthereum.vue @@ -110,7 +110,7 @@ import { onMounted, watch } from "vue" import { $, $$, $computed, $ref } from "vue/macros" import { searchProfilesByEthereumAddress } from "@/api/search" -import { guest, Profile, ProfileWrapper } from "@/api/users" +import { defaultProfile, Profile, ProfileWrapper } from "@/api/users" import { cancelSubscription, getSubscriptionConfig, @@ -137,7 +137,7 @@ const { instance } = $(useInstanceInfo()) const { connectWallet: connectEthereumWallet } = useWallet() const recipient = new ProfileWrapper(props.profile) const recipientEthereumAddress = recipient.getVerifiedEthereumAddress() -let sender = $ref(new ProfileWrapper(currentUser || guest())) +let sender = $ref(new ProfileWrapper(currentUser || defaultProfile())) let { walletAddress, walletError, getSigner } = $(useWallet()) let subscriptionsEnabled = $ref(null) let subscriptionConfig = $ref(null) diff --git a/src/components/SubscriptionMonero.vue b/src/components/SubscriptionMonero.vue index 4289292..10c7ae6 100644 --- a/src/components/SubscriptionMonero.vue +++ b/src/components/SubscriptionMonero.vue @@ -124,7 +124,7 @@ import { getPricePerMonth, Invoice, } from "@/api/subscriptions-monero" -import { guest, Profile, ProfilePaymentOption, ProfileWrapper } from "@/api/users" +import { defaultProfile, Profile, ProfilePaymentOption, ProfileWrapper } from "@/api/users" import Avatar from "@/components/Avatar.vue" import Loader from "@/components/Loader.vue" import QrCode from "@/components/QrCode.vue" @@ -142,7 +142,7 @@ const { currentUser } = $(useCurrentUser()) const recipient = new ProfileWrapper(props.profile) const senderAcct = $ref("") let senderError = $ref(null) -let sender = $ref(new ProfileWrapper(currentUser || guest())) +let sender = $ref(new ProfileWrapper(currentUser || defaultProfile())) let subscriptionOption = $ref(null) let subscriptionDetails = $ref(null) const paymentDuration = $ref(1)