diff --git a/src/components/StatusContent.tsx b/src/components/StatusContent.tsx new file mode 100644 index 0000000..ab4eb38 --- /dev/null +++ b/src/components/StatusContent.tsx @@ -0,0 +1,31 @@ +import { useState } from "react"; +import { Form } from "@raycast/api"; + +interface StatusContentProps { + isMarkdown: boolean; +} + +const StatusContent = ({ isMarkdown }: StatusContentProps) => { + const [statusContent, setStatusContent] = useState(""); + const [error, setError] = useState(""); + + return ( + <> + { + setError(!statusContent ? "content should't be empty!" : ""); + }} + /> + + ); +}; + +export default StatusContent; diff --git a/src/components/VisibilityDropdown.tsx b/src/components/VisibilityDropdown.tsx new file mode 100644 index 0000000..e814908 --- /dev/null +++ b/src/components/VisibilityDropdown.tsx @@ -0,0 +1,31 @@ +import { getPreferenceValues, Color, Icon, Form } from "@raycast/api"; +import { Preference, VisibilityOption } from "../types"; + +const VisibilityDropdown = () => { + const { defaultVisibility }: Preference = getPreferenceValues(); + + const visibilityOptions: VisibilityOption[] = [ + { value: "public", title: "Public", icon: Icon.Livestream }, + { value: "unlisted", title: "Unlisted", icon: Icon.LivestreamDisabled }, + { value: "private", title: "Followers-only", icon: Icon.TwoPeople }, + { value: "direct", title: "Direct", icon: Icon.Envelope }, + { value: "local", title: "Local-only", icon: Icon.Pin }, + ]; + + return ( + <> + + {visibilityOptions.map(({ value, title, icon }) => ( + + ))} + + + ); +}; + +export default VisibilityDropdown; diff --git a/src/index.tsx b/src/detail-status.tsx similarity index 55% rename from src/index.tsx rename to src/detail-status.tsx index c770f75..d2cdb9c 100644 --- a/src/index.tsx +++ b/src/detail-status.tsx @@ -1,23 +1,18 @@ -import { useEffect } from "react"; +import { useEffect,useState } from "react"; import { Form, ActionPanel, Action, showToast } from "@raycast/api"; -import { authorize } from "./oauth"; import { postNewStatus } from "./api"; -import { Status, VisibilityOption } from "./types"; +import { Status } from "./types"; +import { authorize } from "./oauth"; +import VisibilityDropdown from "./components/VisibilityDropdown"; +import StatusContent from "./components/statusContent"; export default function Command() { + const [isMarkdown, setIsMarkdown] = useState(true); useEffect(() => { authorize(); }, []); - const visibilityOptions: VisibilityOption[] = [ - { value: "direct", title: "Direct" }, - { value: "private", title: "Private" }, - { value: "unlisted", title: "Unlisted" }, - { value: "public", title: "Public" }, - { value: "local", title: "Local" }, - ]; - - const handleSubmit = async (values: Status) => { + const handleSubmit = async (values: Partial) => { try { await postNewStatus({ ...values }); showToast({ title: "Submitted form", message: "Status has been posted!" }); @@ -36,15 +31,19 @@ export default function Command() { } > - + - - {visibilityOptions.map(({value, title}) => ( - - ))} - + + ); diff --git a/src/oauth.ts b/src/oauth.ts index 1f97b9b..45f3750 100644 --- a/src/oauth.ts +++ b/src/oauth.ts @@ -46,7 +46,6 @@ const refreshToken = async ( return tokenResponse; }; - export const authorize = async (): Promise => { const { instance } = getPreferenceValues(); const tokenSet = await client.getTokens(); diff --git a/src/simple-status.tsx b/src/simple-status.tsx new file mode 100644 index 0000000..559aad7 --- /dev/null +++ b/src/simple-status.tsx @@ -0,0 +1,74 @@ +import { useEffect, useState } from "react"; +import { Form, ActionPanel, Action, showToast, popToRoot, LaunchProps } from "@raycast/api"; +import { postNewStatus } from "./api"; +import { Status } from "./types"; +import { authorize } from "./oauth"; +import VisibilityDropdown from "./components/VisibilityDropdown"; + +export default function Command(props: LaunchProps<{ draftValues: Partial }>) { + const { draftValues } = props; + const [statusContent, setStatusContent] = useState(draftValues?.status || ""); + const [cw, setCw] = useState(draftValues?.spoiler_text || ""); + const [isMarkdown, setIsMarkdown] = useState(true); + const [error, setError] = useState(false); + + useEffect(() => { + authorize(); + }, []); + + const handleSubmit = async () => { + try { + const newStatus: Partial = { + spoiler_text: cw, + status: statusContent, + content_type: isMarkdown ? "text/markdown" : "text/plain", + visibility: "direct", + }; + + console.log(newStatus); + await postNewStatus(newStatus); + setCw('') + setStatusContent('') + showToast({ title: "Submitted form", message: "Status has been posted!" }); + popToRoot(); + } catch (error) { + console.error(error); + showToast({ title: "Error", message: "Something went wrong!" }); + } + }; + + return ( +
+ + + } + > + + { + setError(!statusContent); + }} + /> + {/* */} + + + ); +} diff --git a/src/types.ts b/src/types.ts index 45ce8b8..5634099 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,15 +1,22 @@ -export type VisibilityScope = "public" | "unlisted" | "direct" | "private" | "local" - -export interface VisibilityOption { - title: string; - value: VisibilityScope -} - +import type {Icon} from '@raycast/api' export interface Preference { instance: string; defaultVisibility: VisibilityScope; } +export type VisibilityScope = "public" | "unlisted" | "direct" | "private" | "local"; + +export interface VisibilityOption { + title: string; + value: VisibilityScope; + icon: Icon +} + +interface Application { + name: string; + website: string; +} + export interface Credentials { client_id: string; client_secret: string; @@ -24,170 +31,35 @@ export interface ApiResponse { id: number; created_at: string; text: string; -}; - -export interface AppResponse { - client_id: string; - client_secret: string; - id: string; - name: string; - redirect_uri: string; - website: string; - vapid_key: string; } interface Poll { expired_in: number; - hide_totals?: boolean | string; + hide_totals?: boolean | string; multiple?: boolean | string | number; - options: string[] + options: string[]; } export interface Status { - content_type?: string; - expires_in?: number; - in_reply_to_conversation_id?: string; - in_reply_to_id?: string; - language?: string; - media_ids?: string[]; - poll?: Poll; - preview?: boolean | string | number; - scheduled_at?: string; - sensitive?: string | boolean | number; - spoiler_text?: string; - status?: string; - to?: string[]; - visibility?: VisibilityScope; + spoiler_text: string; + status: string; + content_type: string; + expires_in: number; + in_reply_to_conversation_id: string; + in_reply_to_id: string; + language: string; + media_ids: string[]; + poll: Poll; + preview: boolean | string | number; + scheduled_at: Date; + sensitive: string | boolean | number; + to: string[]; + visibility: VisibilityScope; } -// interface Account { -// acct: string; -// avatar: string; -// avatar_static: string; -// bot: boolean; -// created_at: string; -// display_name: string; -// emojis: Emoji[]; -// fields: Field[]; -// followers_count: number; -// following_count: number; -// header: string; -// header_static: string; -// id: string; -// is_confirmed: boolean; -// note: string; -// pleroma: Pleroma; -// source: Source; -// statuses_count: number; -// url: string; -// username: string; -// } - -// interface Emoji { -// shortcode: string; -// static_url: string; -// url: string; -// visible_in_picker: boolean; -// } -// interface Field { -// name: string; -// value: string; -// verified_at: string | null; -// } - -// interface Pleroma { -// background_image: null; -// hide_favorites: boolean; -// hide_followers: boolean; -// hide_followers_count: boolean; -// hide_follows: boolean; -// hide_follows_count: boolean; -// is_admin: boolean; -// is_confirmed: boolean; -// is_moderator: boolean; -// relationship: Relationship; -// skip_thread_containment: boolean; -// tags: any[]; -// } -// type Actor = "Application" | "Group" | "Organization" | "Person" | "Service" - -// interface Relationship { -// blocked_by: boolean; -// blocking: boolean; -// domain_blocking: boolean; -// endorsed: boolean; -// followed_by: boolean; -// following: boolean; -// id: string; -// muting: boolean; -// muting_notifications: boolean; -// note: string; -// notifying: boolean; -// requested: boolean; -// showing_reblogs: boolean; -// subscribing: boolean; -// } - -// interface Source { -// fields: Field[]; -// note: string; -// pleroma: SourcePleroma; -// privacy: VisibilityScope; -// sensitive: boolean; -// } - -// interface SourcePleroma { -// actor_type: Actor; -// discoverable: boolean; -// no_rich_text: boolean; -// show_role: boolean; -// } - -// interface StatusResponse { -// account: Account; -// application: null; -// bookmarked: boolean; -// card: null; -// content: string; -// created_at: string; -// emojis: any[]; -// favourited: boolean; -// favourites_count: number; -// id: string; -// in_reply_to_account_id: null; -// in_reply_to_id: null; -// language: null; -// media_attachments: any[]; -// mentions: any[]; -// muted: boolean; -// pinned: boolean; -// pleroma: StatusPleroma; -// poll: null; -// reblog: null; -// reblogged: boolean; -// reblogs_count: number; -// replies_count: number; -// sensitive: boolean; -// spoiler_text: string; -// tags: any[]; -// uri: string; -// url: string; -// visibility: string; -// } - -// interface StatusPleroma { -// content: PleromaContent; -// context: string; -// conversation_id: number; -// direct_conversation_id: null; -// emoji_reactions: any[]; -// expires_at: null; -// in_reply_to_account_acct: null; -// local: boolean; -// spoiler_text: PleromaContent; -// thread_muted: boolean; -// } - -// interface PleromaContent { -// "text/plain": string; -// } \ No newline at end of file +export interface StatusResponse { + id: string; + create_at: Date; + content: string; + application: Application +} \ No newline at end of file