Allow to set visibility in post editor

This commit is contained in:
silverpill 2022-01-07 22:12:58 +00:00
parent db234bd01b
commit 420e51f833
5 changed files with 87 additions and 20 deletions

View file

@ -108,6 +108,7 @@ export async function getPostContext(
export interface PostData { export interface PostData {
content: string; content: string;
in_reply_to_id: string | null; in_reply_to_id: string | null;
visibility: string;
} }
export async function createPost( export async function createPost(
@ -121,6 +122,7 @@ export async function createPost(
status: postData.content, status: postData.content,
"media_ids[]": attachment ? [attachment.id] : null, "media_ids[]": attachment ? [attachment.id] : null,
in_reply_to_id: postData.in_reply_to_id, in_reply_to_id: postData.in_reply_to_id,
visibility: postData.visibility,
} }
const response = await http(url, { const response = await http(url, {
method: "POST", method: "POST",

View file

@ -21,8 +21,7 @@
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
> >
<img v-if="post.visibility === 'public'" :src="require('@/assets/feather/globe.svg')"> <visibility-icon :visibility="post.visibility"></visibility-icon>
<img v-else-if="post.visibility === 'direct'" :src="require('@/assets/feather/lock.svg')">
</a> </a>
<a <a
v-if="inThread && post.in_reply_to_id" v-if="inThread && post.in_reply_to_id"
@ -109,14 +108,14 @@
<img :src="require('@/assets/forkawesome/diamond.svg')"> <img :src="require('@/assets/forkawesome/diamond.svg')">
</a> </a>
<div <div
class="post-menu-wrapper" class="dropdown-menu-wrapper"
v-if="canSaveToIpfs() || canMintToken() || canDeletePost()" v-if="canSaveToIpfs() || canMintToken() || canDeletePost()"
v-click-away="hideMenu" v-click-away="hideMenu"
> >
<a class="icon" title="More" @click="toggleMenu()"> <a class="icon" title="More" @click="toggleMenu()">
<img :src="require('@/assets/feather/more-horizontal.svg')"> <img :src="require('@/assets/feather/more-horizontal.svg')">
</a> </a>
<ul v-if="menuVisible" class="post-menu"> <ul v-if="menuVisible" class="dropdown-menu">
<li v-if="canSaveToIpfs()"> <li v-if="canSaveToIpfs()">
<a <a
class="icon" class="icon"
@ -191,6 +190,7 @@ import {
import Avatar from "@/components/Avatar.vue" import Avatar from "@/components/Avatar.vue"
import CryptoAddress from "@/components/CryptoAddress.vue" import CryptoAddress from "@/components/CryptoAddress.vue"
import PostEditor from "@/components/PostEditor.vue" import PostEditor from "@/components/PostEditor.vue"
import VisibilityIcon from "@/components/VisibilityIcon.vue"
import { useInstanceInfo } from "@/store/instance" import { useInstanceInfo } from "@/store/instance"
import { useCurrentUser } from "@/store/user" import { useCurrentUser } from "@/store/user"
import { CRYPTOCURRENCIES } from "@/utils/cryptocurrencies" import { CRYPTOCURRENCIES } from "@/utils/cryptocurrencies"
@ -208,6 +208,7 @@ interface PaymentOption {
Avatar, Avatar,
CryptoAddress, CryptoAddress,
PostEditor, PostEditor,
VisibilityIcon,
}, },
}) })
export default class PostComponent extends Vue { export default class PostComponent extends Vue {
@ -567,21 +568,8 @@ export default class PostComponent extends Vue {
} }
} }
.post-menu-wrapper { .dropdown-menu-wrapper {
position: relative; @include post-dropdown-menu;
}
.post-menu {
background-color: $block-background-color;
border: 1px solid $separator-color;
border-radius: $btn-border-radius;
display: flex;
flex-direction: column;
gap: $block-inner-padding / 2;
padding: $block-inner-padding / 2;
position: absolute;
white-space: nowrap;
z-index: 3;
} }
.crypto-widget { .crypto-widget {

View file

@ -30,6 +30,36 @@
@change="uploadAttachment($event.target.files)" @change="uploadAttachment($event.target.files)"
> >
</a> </a>
<div
class="dropdown-menu-wrapper"
v-click-away="hideVisibilityMenu"
>
<a class="icon" title="Post visibility" @click="toggleVisibilityMenu()">
<visibility-icon :visibility="visibility"></visibility-icon>
</a>
<ul v-if="visibilityMenuVisible" class="dropdown-menu">
<li>
<a
class="icon"
title="Public"
@click="hideVisibilityMenu(); visibility = 'public'"
>
<visibility-icon :visibility="'public'"></visibility-icon>
<span>Public</span>
</a>
</li>
<li>
<a
class="icon"
title="Direct"
@click="hideVisibilityMenu(); visibility = 'direct'"
>
<visibility-icon :visibility="'direct'"></visibility-icon>
<span>Direct</span>
</a>
</li>
</ul>
</div>
<div class="character-counter" title="Characters left"> <div class="character-counter" title="Characters left">
{{ characterCounter }} {{ characterCounter }}
</div> </div>
@ -61,6 +91,7 @@ import { Prop } from "vue-property-decorator"
import { createPost, Attachment, uploadAttachment } from "@/api/posts" import { createPost, Attachment, uploadAttachment } from "@/api/posts"
import { User } from "@/api/users" import { User } from "@/api/users"
import Avatar from "@/components/Avatar.vue" import Avatar from "@/components/Avatar.vue"
import VisibilityIcon from "@/components/VisibilityIcon.vue"
import { useCurrentUser } from "@/store/user" import { useCurrentUser } from "@/store/user"
import { setupAutoResize } from "@/utils/autoresize" import { setupAutoResize } from "@/utils/autoresize"
import { renderMarkdownLite } from "@/utils/markdown" import { renderMarkdownLite } from "@/utils/markdown"
@ -71,6 +102,7 @@ const POST_CHARACTER_LIMIT = 1000
@Options({ @Options({
components: { components: {
Avatar, Avatar,
VisibilityIcon,
}, },
}) })
export default class PostEditor extends Vue { export default class PostEditor extends Vue {
@ -79,7 +111,10 @@ export default class PostEditor extends Vue {
inReplyTo: string | null = null inReplyTo: string | null = null
content = "" content = ""
visibility = "public"
attachment: Attachment | null = null attachment: Attachment | null = null
visibilityMenuVisible = false
errorMessage: string | null = null errorMessage: string | null = null
$refs!: { $refs!: {
@ -113,6 +148,14 @@ export default class PostEditor extends Vue {
) )
} }
toggleVisibilityMenu() {
this.visibilityMenuVisible = !this.visibilityMenuVisible
}
hideVisibilityMenu() {
this.visibilityMenuVisible = false
}
get characterCounter(): number { get characterCounter(): number {
return (POST_CHARACTER_LIMIT - this.content.length) return (POST_CHARACTER_LIMIT - this.content.length)
} }
@ -122,6 +165,7 @@ export default class PostEditor extends Vue {
const postData = { const postData = {
content, content,
in_reply_to_id: this.inReplyTo, in_reply_to_id: this.inReplyTo,
visibility: this.visibility,
} }
let post let post
try { try {
@ -198,10 +242,11 @@ textarea {
color: $secondary-text-color; color: $secondary-text-color;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
font-weight: bold; gap: $block-inner-padding / 2;
padding: $block-inner-padding / 1.5 $block-inner-padding; padding: $block-inner-padding / 1.5 $block-inner-padding;
.character-counter { .character-counter {
font-weight: bold;
margin-left: auto; margin-left: auto;
} }
@ -210,6 +255,10 @@ textarea {
} }
} }
.dropdown-menu-wrapper {
@include post-dropdown-menu;
}
.submit-btn-wrapper { .submit-btn-wrapper {
align-items: center; align-items: center;
display: flex; display: flex;

View file

@ -0,0 +1,11 @@
<template>
<img v-if="visibility === 'public'" :src="require('@/assets/feather/globe.svg')">
<img v-else-if="visibility === 'direct'" :src="require('@/assets/feather/lock.svg')">
</template>
<script setup lang="ts">
/* eslint-disable no-undef */
defineProps<{
visibility: string,
}>()
</script>

View file

@ -82,6 +82,23 @@
} }
} }
@mixin post-dropdown-menu {
position: relative;
.dropdown-menu {
background-color: $block-background-color;
border: 1px solid $separator-color;
border-radius: $btn-border-radius;
display: flex;
flex-direction: column;
gap: $block-inner-padding / 2;
padding: $block-inner-padding / 2;
position: absolute;
white-space: nowrap;
z-index: 3;
}
}
@mixin block-btn { @mixin block-btn {
.btn { .btn {
background-color: $btn-background-hover-color; background-color: $btn-background-hover-color;