feat: Polish UI, add new functionality to composer

This commit is contained in:
Jesse Wierzbinski 2024-05-11 18:34:03 -10:00
parent ddebe77e5b
commit 2cc3d2ea7a
No known key found for this signature in database
5 changed files with 76 additions and 6 deletions

View file

@ -0,0 +1,18 @@
<template>
<button v-bind="$props"
:class="['rounded text-gray-300 hover:bg-dark-900/70 p-2 flex items-center justify-center duration-200', toggled && 'bg-pink-500/70 hover:bg-pink-900/70']">
<slot />
</button>
</template>
<script lang="ts" setup>
import type { ButtonHTMLAttributes } from "vue";
interface Props extends /* @vue-ignore */ ButtonHTMLAttributes { }
defineProps<
Props & {
toggled?: boolean;
}
>();
</script>

View file

@ -14,14 +14,37 @@
<SocialElementsNotesNote :note="respondingTo" :small="true" :disabled="true" /> <SocialElementsNotesNote :note="respondingTo" :small="true" :disabled="true" />
</OverlayScrollbarsComponent> </OverlayScrollbarsComponent>
</div> </div>
<textarea :disabled="submitting" ref="textarea" v-model="content" placeholder="You can use Markdown here!" <textarea :disabled="submitting" ref="textarea" v-model="content" :placeholder="chosenSplash"
class="resize-none min-h-48 prose prose-invert max-h-[70dvh] w-full p-0 focus:!ring-0 !ring-none !border-none !outline-none placeholder:text-zinc-500 bg-transparent appearance-none focus:!border-none focus:!outline-none disabled:cursor-not-allowed"></textarea> class="resize-none min-h-48 prose prose-invert max-h-[70dvh] w-full p-0 focus:!ring-0 !ring-none !border-none !outline-none placeholder:text-zinc-500 bg-transparent appearance-none focus:!border-none focus:!outline-none disabled:cursor-not-allowed"></textarea>
<div <div
:class="['absolute bottom-0 right-0 p-2 text-gray-400 font-semibold text-xs', remainingCharacters < 0 && 'text-red-500']"> :class="['absolute bottom-0 right-0 p-2 text-gray-400 font-semibold text-xs', remainingCharacters < 0 && 'text-red-500']">
{{ remainingCharacters }} {{ remainingCharacters }}
</div> </div>
</div> </div>
<!-- Content warning textbox -->
<div v-if="cw !== null" class="mb-4">
<input type="text" placeholder="Add a content warning"
class="w-full p-2 mt-1 text-sm prose prose-invert bg-dark-900 rounded focus:!ring-0 !ring-none !border-none !outline-none placeholder:text-zinc-500 appearance-none focus:!border-none focus:!outline-none" />
</div>
<div class="flex flex-row gap-1 border-white/20"> <div class="flex flex-row gap-1 border-white/20">
<ComposerButton title="Mention someone">
<Icon name="tabler:at" class="size-6" aria-hidden="true" />
</ComposerButton>
<ComposerButton title="Toggle Markdown" @click="markdown = !markdown" :toggled="markdown">
<Icon :name="markdown ? 'tabler:markdown' : 'tabler:markdown-off'" class="size-6" aria-hidden="true" />
</ComposerButton>
<ComposerButton title="Use a custom emoji">
<Icon name="tabler:mood-smile" class="size-6" aria-hidden="true" />
</ComposerButton>
<ComposerButton title="Add media">
<Icon name="tabler:photo-up" class="size-6" aria-hidden="true" />
</ComposerButton>
<ComposerButton title="Add a file">
<Icon name="tabler:file-upload" class="size-6" aria-hidden="true" />
</ComposerButton>
<ComposerButton title="Add content warning" @click="cw = cw === null ? '' : null" :toggled="cw !== null">
<Icon name="tabler:rating-18-plus" class="size-6" aria-hidden="true" />
</ComposerButton>
<ButtonsPrimary :loading="submitting" @click="send" class="ml-auto rounded-full"> <ButtonsPrimary :loading="submitting" @click="send" class="ml-auto rounded-full">
<span>Send!</span> <span>Send!</span>
</ButtonsPrimary> </ButtonsPrimary>
@ -38,10 +61,18 @@ const textarea = ref<HTMLTextAreaElement | undefined>(undefined);
const { input: content } = useTextareaAutosize({ const { input: content } = useTextareaAutosize({
element: textarea, element: textarea,
}); });
const { Control_Enter, Command_Enter } = useMagicKeys(); const { Control_Enter, Command_Enter, Control_Alt } = useMagicKeys();
const respondingTo = ref<Status | null>(null); const respondingTo = ref<Status | null>(null);
const respondingType = ref<"reply" | "quote" | null>(null); const respondingType = ref<"reply" | "quote" | null>(null);
const me = useMe(); const me = useMe();
const cw = ref(null as string | null);
const markdown = ref(true);
const splashes = useConfig().COMPOSER_SPLASHES;
const chosenSplash = ref(splashes[Math.floor(Math.random() * splashes.length)]);
watch(Control_Alt, () => {
chosenSplash.value = splashes[Math.floor(Math.random() * splashes.length)];
});
onMounted(() => { onMounted(() => {
useListen("composer:reply", (note: Status) => { useListen("composer:reply", (note: Status) => {
@ -86,7 +117,7 @@ const send = async () => {
}, },
body: JSON.stringify({ body: JSON.stringify({
status: content.value.trim(), status: content.value.trim(),
content_type: "text/markdown", content_type: markdown.value ? "text/markdown" : "text/plain",
in_reply_to_id: in_reply_to_id:
respondingType.value === "reply" respondingType.value === "reply"
? respondingTo.value?.id ? respondingTo.value?.id

View file

@ -44,10 +44,14 @@
<h3 v-if="tokenData" <h3 v-if="tokenData"
class="font-semibold text-gray-300 text-xs uppercase opacity-0 group-hover:opacity-100 duration-200"> class="font-semibold text-gray-300 text-xs uppercase opacity-0 group-hover:opacity-100 duration-200">
Posts</h3> Posts</h3>
<ButtonsBase v-if="tokenData" @click="compose" <ButtonsBase v-if="tokenData" @click="compose" title="Open composer (shortcut: n)"
class="flex flex-row text-left items-center justify-start gap-3 text-lg hover:ring-1 ring-white/10 bg-gradient-to-tr from-pink-300 via-purple-300 to-indigo-400 overflow-hidden h-12 w-full duration-200"> class="flex flex-row text-left items-center justify-start gap-3 text-lg hover:ring-1 ring-white/10 bg-gradient-to-tr from-pink-300 via-purple-300 to-indigo-400 overflow-hidden h-12 w-full duration-200">
<Icon name="tabler:writing" class="shrink-0 text-2xl" /> <Icon name="tabler:writing" class="shrink-0 text-2xl" />
<span class="pr-28 line-clamp-1">Compose</span> <span class="pr-28 line-clamp-1">Compose</span>
<kbd class="text-xs font-semibold rounded bg-dark-500 font-mono px-1 flex flex-row">
<Icon name="tabler:keyboard" class="size-4 inline" aria-hidden="true" />
<Icon name="tabler:letter-n-small" class="size-4 inline -mr-1" aria-hidden="true" />
</kbd>
</ButtonsBase> </ButtonsBase>
</ClientOnly> </ClientOnly>
</div> </div>
@ -210,7 +214,7 @@ const signOut = async () => {
tokenData.value.access_token, tokenData.value.access_token,
tokenData.value.access_token, tokenData.value.access_token,
) )
.catch(() => {}); .catch(() => { });
tokenData.value = null; tokenData.value = null;
me.value = null; me.value = null;

View file

@ -8,5 +8,20 @@ export const useConfig = () => {
link: "https://sk22.github.io/megalodon/", link: "https://sk22.github.io/megalodon/",
}, },
], ],
COMPOSER_SPLASHES: [
"What's on your mind?",
"What's happening?",
"Meow meow meow meow meow",
"Just arrived at Luna Nova Academy",
"I'm a little teapot, short and stout",
"Hey, you. You're finally awake. You were trying to cross the border, right?",
"Aren't you a little short for a stormtrooper?",
"I'm a leaf on the wind. Watch how I soar.",
"I am Groot.",
"Hello everybody, my name is Markiplier",
"I'm Commander Shepard, and this is my favorite website on the Citadel",
"I'm sorry, Dave. I'm afraid I can't do that.",
"I am the Senate",
],
}; };
}; };

View file

@ -68,8 +68,10 @@ useServerSeoMeta({
const { n } = useMagicKeys(); const { n } = useMagicKeys();
watchEffect(() => { watchEffect(async () => {
if (n.value) { if (n.value) {
// Wait 50ms
await new Promise((resolve) => setTimeout(resolve, 50));
useEvent("composer:open"); useEvent("composer:open");
} }
}); });