Convert all remaining components into script-setup format
This commit is contained in:
parent
5f2506c170
commit
78dfbfc396
4 changed files with 250 additions and 277 deletions
|
@ -10,7 +10,7 @@
|
|||
<div class="textarea-group">
|
||||
<textarea
|
||||
id="content"
|
||||
ref="postFormContent"
|
||||
ref="postFormContentRef"
|
||||
v-model="content"
|
||||
rows="1"
|
||||
required
|
||||
|
@ -29,7 +29,7 @@
|
|||
<img :src="require('@/assets/feather/paperclip.svg')">
|
||||
<input
|
||||
type="file"
|
||||
ref="attachmentUploadInput"
|
||||
ref="attachmentUploadInputRef"
|
||||
accept="image/*"
|
||||
style="display: none;"
|
||||
@change="onAttachmentUpload($event)"
|
||||
|
@ -85,9 +85,9 @@
|
|||
</form>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue, setup } from "vue-class-component"
|
||||
import { Prop } from "vue-property-decorator"
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted } from "vue"
|
||||
import { $, $computed, $ref } from "vue/macros"
|
||||
|
||||
import {
|
||||
Visibility,
|
||||
|
@ -107,127 +107,119 @@ import { setupAutoResize, triggerResize } from "@/utils/autoresize"
|
|||
import { renderMarkdownLite } from "@/utils/markdown"
|
||||
import { fileToDataUrl, dataUrlToBase64 } from "@/utils/upload"
|
||||
|
||||
@Options({
|
||||
components: {
|
||||
Avatar,
|
||||
VisibilityIcon,
|
||||
},
|
||||
const visibilityMap = Object.entries(VISIBILITY_MAP)
|
||||
|
||||
const { currentUser, ensureAuthToken } = $(useCurrentUser())
|
||||
const { instance, getActorAddress } = $(useInstanceInfo())
|
||||
|
||||
/* eslint-disable-next-line no-undef */
|
||||
const props = defineProps<{
|
||||
inReplyTo: Post | null,
|
||||
}>()
|
||||
|
||||
/* eslint-disable-next-line no-undef, func-call-spacing */
|
||||
const emit = defineEmits<{
|
||||
(event: "post-created", post: Post): void,
|
||||
}>()
|
||||
|
||||
const postFormContentRef = $ref<HTMLTextAreaElement | null>(null)
|
||||
const attachmentUploadInputRef = $ref<HTMLInputElement | null>(null)
|
||||
|
||||
let content = $ref("")
|
||||
let attachment = $ref<Attachment | null>(null)
|
||||
let visibility = $ref(Visibility.Public)
|
||||
|
||||
let visibilityMenuVisible = $ref(false)
|
||||
let errorMessage = $ref<string | null>(null)
|
||||
|
||||
const author = $computed<User | null>(() => {
|
||||
return currentUser
|
||||
})
|
||||
export default class PostEditor extends Vue {
|
||||
|
||||
@Prop()
|
||||
inReplyTo: Post | null = null
|
||||
|
||||
content = ""
|
||||
attachment: Attachment | null = null
|
||||
visibility = Visibility.Public
|
||||
mentions: string[] = []
|
||||
|
||||
visibilityMenuVisible = false
|
||||
errorMessage: string | null = null
|
||||
|
||||
$refs!: {
|
||||
postFormContent: HTMLTextAreaElement,
|
||||
attachmentUploadInput: HTMLInputElement,
|
||||
}
|
||||
|
||||
private store = setup(() => {
|
||||
const { currentUser, ensureAuthToken } = useCurrentUser()
|
||||
const { instance, getActorAddress } = useInstanceInfo()
|
||||
return { currentUser, ensureAuthToken, instance, getActorAddress }
|
||||
})
|
||||
|
||||
get author(): User | null {
|
||||
return this.store.currentUser
|
||||
}
|
||||
|
||||
created() {
|
||||
if (this.inReplyTo) {
|
||||
if (props.inReplyTo) {
|
||||
const mentions: Mention[] = [
|
||||
this.inReplyTo.account,
|
||||
...this.inReplyTo.mentions,
|
||||
props.inReplyTo.account,
|
||||
...props.inReplyTo.mentions,
|
||||
]
|
||||
this.content = mentions
|
||||
.filter(mention => mention.id !== this.store.currentUser?.id)
|
||||
.map(mention => "@" + this.store.getActorAddress(mention))
|
||||
content = mentions
|
||||
.filter(mention => mention.id !== currentUser?.id)
|
||||
.map(mention => "@" + getActorAddress(mention))
|
||||
// Remove duplicates
|
||||
.filter((mention, index, mentions) => mentions.indexOf(mention) === index)
|
||||
.join(" ")
|
||||
}
|
||||
if (this.inReplyTo && this.inReplyTo.visibility !== Visibility.Public) {
|
||||
this.visibility = Visibility.Direct
|
||||
}
|
||||
}
|
||||
}
|
||||
if (props.inReplyTo && props.inReplyTo.visibility !== Visibility.Public) {
|
||||
visibility = Visibility.Direct
|
||||
}
|
||||
|
||||
mounted() {
|
||||
setupAutoResize(this.$refs.postFormContent)
|
||||
onMounted(() => {
|
||||
if (postFormContentRef) {
|
||||
setupAutoResize(postFormContentRef)
|
||||
}
|
||||
})
|
||||
|
||||
selectAttachment() {
|
||||
this.$refs.attachmentUploadInput.click()
|
||||
function selectAttachment() {
|
||||
if (attachmentUploadInputRef) {
|
||||
attachmentUploadInputRef.click()
|
||||
}
|
||||
}
|
||||
|
||||
async onAttachmentUpload(event: Event) {
|
||||
async function onAttachmentUpload(event: Event) {
|
||||
const files = (event.target as HTMLInputElement).files
|
||||
if (!files) {
|
||||
return
|
||||
}
|
||||
const imageDataUrl = await fileToDataUrl(files[0])
|
||||
const imageBase64 = dataUrlToBase64(imageDataUrl)
|
||||
this.attachment = await uploadAttachment(
|
||||
this.store.ensureAuthToken(),
|
||||
attachment = await uploadAttachment(
|
||||
ensureAuthToken(),
|
||||
imageBase64,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
get visibilityMap() {
|
||||
return Object.entries(VISIBILITY_MAP)
|
||||
}
|
||||
function toggleVisibilityMenu() {
|
||||
visibilityMenuVisible = !visibilityMenuVisible
|
||||
}
|
||||
|
||||
toggleVisibilityMenu() {
|
||||
this.visibilityMenuVisible = !this.visibilityMenuVisible
|
||||
}
|
||||
function hideVisibilityMenu() {
|
||||
visibilityMenuVisible = false
|
||||
}
|
||||
|
||||
hideVisibilityMenu() {
|
||||
this.visibilityMenuVisible = false
|
||||
}
|
||||
|
||||
getCharacterCount(): number {
|
||||
if (!this.store.instance) {
|
||||
function getCharacterCount(): number {
|
||||
if (!instance) {
|
||||
return 0
|
||||
}
|
||||
return (this.store.instance.post_character_limit - this.content.length)
|
||||
}
|
||||
return (instance.post_character_limit - content.length)
|
||||
}
|
||||
|
||||
async publish() {
|
||||
const content = renderMarkdownLite(this.content)
|
||||
async function publish() {
|
||||
const contentRendered = renderMarkdownLite(content)
|
||||
const postData = {
|
||||
content,
|
||||
in_reply_to_id: this.inReplyTo ? this.inReplyTo.id : null,
|
||||
visibility: this.visibility,
|
||||
mentions: this.mentions,
|
||||
content: contentRendered,
|
||||
in_reply_to_id: props.inReplyTo ? props.inReplyTo.id : null,
|
||||
visibility: visibility,
|
||||
mentions: [],
|
||||
}
|
||||
let post
|
||||
try {
|
||||
post = await createPost(
|
||||
this.store.ensureAuthToken(),
|
||||
ensureAuthToken(),
|
||||
postData,
|
||||
this.attachment,
|
||||
attachment,
|
||||
)
|
||||
} catch (error: any) {
|
||||
this.errorMessage = error.message
|
||||
errorMessage = error.message
|
||||
return
|
||||
}
|
||||
// Refresh editor
|
||||
this.errorMessage = null
|
||||
this.attachment = null
|
||||
this.content = ""
|
||||
this.$nextTick(() => {
|
||||
triggerResize(this.$refs.postFormContent)
|
||||
})
|
||||
this.$emit("post-created", post)
|
||||
errorMessage = null
|
||||
attachment = null
|
||||
content = ""
|
||||
if (postFormContentRef) {
|
||||
await nextTick()
|
||||
triggerResize(postFormContentRef)
|
||||
}
|
||||
|
||||
emit("post-created", post)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<sidebar-layout>
|
||||
<template #content>
|
||||
<post-editor @post-created="insertPost"></post-editor>
|
||||
<post-editor :in-reply-to="null" @post-created="insertPost"></post-editor>
|
||||
<post-list :posts="posts" @load-next-page="loadNextPage"></post-list>
|
||||
</template>
|
||||
</sidebar-layout>
|
||||
|
|
|
@ -20,7 +20,12 @@
|
|||
<div class="form-title">Want to join?</div>
|
||||
<div class="form-control">
|
||||
<div class="input-group">
|
||||
<input id="username" v-model="username" required placeholder="Username">
|
||||
<input
|
||||
id="username"
|
||||
v-model="username"
|
||||
required
|
||||
placeholder="Username"
|
||||
>
|
||||
<div class="addon">@{{ instance.uri }}</div>
|
||||
</div>
|
||||
<div class="form-message">Only letters, numbers and underscores are allowed.</div>
|
||||
|
@ -48,48 +53,37 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue, setup } from "vue-class-component"
|
||||
<script setup lang="ts">
|
||||
import { $, $ref } from "vue/macros"
|
||||
import { useRouter } from "vue-router"
|
||||
|
||||
import {
|
||||
createUser,
|
||||
getAccessToken,
|
||||
getCurrentUser,
|
||||
} from "@/api/users"
|
||||
import { InstanceInfo } from "@/api/instance"
|
||||
import Loader from "@/components/Loader.vue"
|
||||
import { useInstanceInfo } from "@/store/instance"
|
||||
import { useCurrentUser } from "@/store/user"
|
||||
import { createEip4361_SignedMessage, getWallet } from "@/utils/ethereum"
|
||||
|
||||
@Options({
|
||||
components: { Loader },
|
||||
})
|
||||
export default class LandingPage extends Vue {
|
||||
const router = useRouter()
|
||||
const { setCurrentUser, setAuthToken } = useCurrentUser()
|
||||
const { instance } = $(useInstanceInfo())
|
||||
|
||||
username = ""
|
||||
inviteCode: string | null = null
|
||||
isLoading = false
|
||||
loginErrorMessage: string | null = null
|
||||
registrationErrorMessage: string | null = null
|
||||
const username = $ref("")
|
||||
const inviteCode = $ref<string | null>(null)
|
||||
let isLoading = $ref(false)
|
||||
let loginErrorMessage = $ref<string | null>(null)
|
||||
let registrationErrorMessage = $ref<string | null>(null)
|
||||
|
||||
private store = setup(() => {
|
||||
const { setCurrentUser, setAuthToken } = useCurrentUser()
|
||||
const { instance } = useInstanceInfo()
|
||||
return { setCurrentUser, setAuthToken, instance }
|
||||
})
|
||||
|
||||
get instance(): InstanceInfo | null {
|
||||
return this.store.instance
|
||||
}
|
||||
|
||||
async register() {
|
||||
this.registrationErrorMessage = null
|
||||
if (!this.store.instance) {
|
||||
async function register() {
|
||||
registrationErrorMessage = null
|
||||
if (!instance) {
|
||||
return
|
||||
}
|
||||
const instanceHost = this.store.instance.uri
|
||||
const loginMessage = this.store.instance.login_message
|
||||
const instanceHost = instance.uri
|
||||
const loginMessage = instance.login_message
|
||||
const signer = await getWallet()
|
||||
if (!signer) {
|
||||
return
|
||||
|
@ -99,35 +93,35 @@ export default class LandingPage extends Vue {
|
|||
instanceHost,
|
||||
loginMessage,
|
||||
)
|
||||
this.isLoading = true
|
||||
isLoading = true
|
||||
let user
|
||||
let authToken
|
||||
try {
|
||||
user = await createUser({
|
||||
username: this.username,
|
||||
username: username,
|
||||
message,
|
||||
signature,
|
||||
invite_code: this.inviteCode,
|
||||
invite_code: inviteCode,
|
||||
})
|
||||
authToken = await getAccessToken(message, signature)
|
||||
} catch (error: any) {
|
||||
this.isLoading = false
|
||||
this.registrationErrorMessage = error.message
|
||||
isLoading = false
|
||||
registrationErrorMessage = error.message
|
||||
return
|
||||
}
|
||||
this.store.setCurrentUser(user)
|
||||
this.store.setAuthToken(authToken)
|
||||
this.isLoading = false
|
||||
this.$router.push({ name: "home" })
|
||||
}
|
||||
setCurrentUser(user)
|
||||
setAuthToken(authToken)
|
||||
isLoading = false
|
||||
router.push({ name: "home" })
|
||||
}
|
||||
|
||||
async login() {
|
||||
this.loginErrorMessage = null
|
||||
if (!this.store.instance) {
|
||||
async function login() {
|
||||
loginErrorMessage = null
|
||||
if (!instance) {
|
||||
return
|
||||
}
|
||||
const instanceHost = this.store.instance.uri
|
||||
const loginMessage = this.store.instance.login_message
|
||||
const instanceHost = instance.uri
|
||||
const loginMessage = instance.login_message
|
||||
const signer = await getWallet()
|
||||
if (!signer) {
|
||||
return
|
||||
|
@ -143,16 +137,13 @@ export default class LandingPage extends Vue {
|
|||
authToken = await getAccessToken(message, signature)
|
||||
user = await getCurrentUser(authToken)
|
||||
} catch (error: any) {
|
||||
this.loginErrorMessage = error.message
|
||||
loginErrorMessage = error.message
|
||||
return
|
||||
}
|
||||
this.store.setCurrentUser(user)
|
||||
this.store.setAuthToken(authToken)
|
||||
this.$router.push({ name: "home" })
|
||||
}
|
||||
|
||||
setCurrentUser(user)
|
||||
setAuthToken(authToken)
|
||||
router.push({ name: "home" })
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -50,8 +50,10 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue, setup } from "vue-class-component"
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from "vue"
|
||||
import { $, $ref, $computed } from "vue/macros"
|
||||
import { useRoute, useRouter } from "vue-router"
|
||||
|
||||
import { DateTime } from "luxon"
|
||||
|
||||
|
@ -61,79 +63,67 @@ import Avatar from "@/components/Avatar.vue"
|
|||
import { useInstanceInfo } from "@/store/instance"
|
||||
import { useCurrentUser } from "@/store/user"
|
||||
|
||||
@Options({
|
||||
components: {
|
||||
Avatar,
|
||||
},
|
||||
})
|
||||
export default class PostOverlay extends Vue {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { currentUser, authToken } = $(useCurrentUser())
|
||||
const { instance, getActorAddress } = $(useInstanceInfo())
|
||||
|
||||
post: Post | null = null
|
||||
token: TokenMetadata | null = null
|
||||
let post = $ref<Post | null>(null)
|
||||
let token = $ref<TokenMetadata | null>(null)
|
||||
|
||||
private store = setup(() => {
|
||||
const { currentUser, authToken } = useCurrentUser()
|
||||
const { instance, getActorAddress } = useInstanceInfo()
|
||||
return { currentUser, authToken, instance, getActorAddress }
|
||||
})
|
||||
|
||||
async created() {
|
||||
this.post = await getPost(
|
||||
this.store.authToken,
|
||||
this.$route.params.postId as string,
|
||||
onMounted(async () => {
|
||||
post = await getPost(
|
||||
authToken,
|
||||
route.params.postId as string,
|
||||
)
|
||||
const metadataUrl = this.metadataUrl
|
||||
if (metadataUrl) {
|
||||
this.token = await getTokenMetadata(metadataUrl)
|
||||
}
|
||||
}
|
||||
|
||||
canGoBack(): boolean {
|
||||
return this.store.currentUser !== null
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.$router.back()
|
||||
}
|
||||
|
||||
get actorAddress(): string {
|
||||
if (!this.post) {
|
||||
return ""
|
||||
}
|
||||
return this.store.getActorAddress(this.post.account)
|
||||
}
|
||||
|
||||
get transactionUrl(): string | null {
|
||||
const explorerUrl = this.store.instance?.blockchain_explorer_url
|
||||
if (!explorerUrl || !this.post?.token_tx_id) {
|
||||
return null
|
||||
}
|
||||
return `${explorerUrl}/tx/0x${this.post.token_tx_id}`
|
||||
}
|
||||
|
||||
get metadataUrl(): string | null {
|
||||
const gatewayUrl = this.store.instance?.ipfs_gateway_url
|
||||
if (!gatewayUrl || !this.post) {
|
||||
return null
|
||||
}
|
||||
return `${gatewayUrl}/ipfs/${this.post.ipfs_cid}`
|
||||
}
|
||||
|
||||
get imageUrl(): string | null {
|
||||
const gatewayUrl = this.store.instance?.ipfs_gateway_url
|
||||
if (!gatewayUrl || !this.token) {
|
||||
return null
|
||||
}
|
||||
return this.token.image.replace("ipfs://", `${gatewayUrl}/ipfs/`)
|
||||
}
|
||||
|
||||
formatDate(isoDate: string): string {
|
||||
const date = DateTime.fromISO(isoDate)
|
||||
return date.toLocaleString(DateTime.DATE_FULL)
|
||||
token = await getTokenMetadata(metadataUrl)
|
||||
}
|
||||
})
|
||||
|
||||
function canGoBack(): boolean {
|
||||
return currentUser !== null
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
router.back()
|
||||
}
|
||||
|
||||
const actorAddress = $computed<string>(() => {
|
||||
if (!post) {
|
||||
return ""
|
||||
}
|
||||
return getActorAddress(post.account)
|
||||
})
|
||||
|
||||
const transactionUrl = $computed<string | null>(() => {
|
||||
const explorerUrl = instance?.blockchain_explorer_url
|
||||
if (!explorerUrl || !post?.token_tx_id) {
|
||||
return null
|
||||
}
|
||||
return `${explorerUrl}/tx/0x${post.token_tx_id}`
|
||||
})
|
||||
|
||||
const metadataUrl = $computed<string | null>(() => {
|
||||
const gatewayUrl = instance?.ipfs_gateway_url
|
||||
if (!gatewayUrl || !post) {
|
||||
return null
|
||||
}
|
||||
return `${gatewayUrl}/ipfs/${post.ipfs_cid}`
|
||||
})
|
||||
|
||||
const imageUrl = $computed<string | null>(() => {
|
||||
const gatewayUrl = instance?.ipfs_gateway_url
|
||||
if (!gatewayUrl || !token) {
|
||||
return null
|
||||
}
|
||||
return token.image.replace("ipfs://", `${gatewayUrl}/ipfs/`)
|
||||
})
|
||||
|
||||
function formatDate(isoDate: string): string {
|
||||
const date = DateTime.fromISO(isoDate)
|
||||
return date.toLocaleString(DateTime.DATE_FULL)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
Loading…
Reference in a new issue