From 5ce14df8f37db21c1e31bd88e6ef59a8db110b1e Mon Sep 17 00:00:00 2001 From: Liam Neville Date: Wed, 19 Feb 2025 05:02:52 -0500 Subject: [PATCH 01/14] Implement skip 15 seconds, back 15 seconds (#16980) * Implement skip 15 seconds, back 15 seconds * allow skip15, back15 for songs, update changlog + readme --- extensions/spotify-player/CHANGELOG.md | 4 +++ extensions/spotify-player/README.md | 8 +++++ extensions/spotify-player/package.json | 19 ++++++++++- extensions/spotify-player/src/back15.ts | 25 ++++++++++++++ .../spotify-player/src/nowPlayingMenuBar.tsx | 34 +++++++++++++++++++ extensions/spotify-player/src/skip15.ts | 25 ++++++++++++++ 6 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 extensions/spotify-player/src/back15.ts create mode 100644 extensions/spotify-player/src/skip15.ts diff --git a/extensions/spotify-player/CHANGELOG.md b/extensions/spotify-player/CHANGELOG.md index 43b8d14fcaf0c..5dc0dfa2b1d8a 100644 --- a/extensions/spotify-player/CHANGELOG.md +++ b/extensions/spotify-player/CHANGELOG.md @@ -1,5 +1,9 @@ # Spotify Player Changelog +## [Add "Skip 15 Seconds" and "Back 15 Seconds" commands] - 2025-02-18 + +- Added the ability to skip forward or back 15 seconds in the current episode. This adds two new commands as well as two new menu bar items which only show when an 'episode' is playing. + ## [Artist Name Visibility Option] - 2025-02-07 - Added the option to hide the artist's name in the Menu Bar Player. diff --git a/extensions/spotify-player/README.md b/extensions/spotify-player/README.md index 16393b2132681..378d6b2b6d72c 100644 --- a/extensions/spotify-player/README.md +++ b/extensions/spotify-player/README.md @@ -106,6 +106,14 @@ Use this to quickly start playing a song based on your query. Use this to get a playlist generated by Raycast AI based on a prompt. You can then add this playlist to Spotify or queue all the songs directly. +### Skip 15 Seconds + +Use this to skip ahead 15 seconds. + +### Back 15 Seconds + +Use this to go back 15 seconds. + --- In order to use this extension, you'll need to authenticate with Spotify. This extension requires the following permissions [scopes](https://developer.spotify.com/documentation/web-api/concepts/scopes): diff --git a/extensions/spotify-player/package.json b/extensions/spotify-player/package.json index 836663fe9dda4..57b365073badf 100644 --- a/extensions/spotify-player/package.json +++ b/extensions/spotify-player/package.json @@ -31,7 +31,8 @@ "rhesamu", "themitpatel", "litomore", - "enneemme" + "enneemme", + "lineville" ], "pastContributors": [ "bkeys818" @@ -443,6 +444,22 @@ "description": "Start the DJ.", "mode": "no-view", "disabledByDefault": true + }, + { + "name": "skip15", + "title": "Skip 15 Seconds", + "subtitle": "Spotify", + "description": "Skip 15 seconds forward in an episode.", + "mode": "no-view", + "disabledByDefault": true + }, + { + "name": "back15", + "title": "Back 15 Seconds", + "subtitle": "Spotify", + "description": "Back 15 seconds in an episode.", + "mode": "no-view", + "disabledByDefault": true } ], "dependencies": { diff --git a/extensions/spotify-player/src/back15.ts b/extensions/spotify-player/src/back15.ts new file mode 100644 index 0000000000000..522c8825bb605 --- /dev/null +++ b/extensions/spotify-player/src/back15.ts @@ -0,0 +1,25 @@ +import { showHUD } from "@raycast/api"; +import { setSpotifyClient } from "./helpers/withSpotifyClient"; +import { getCurrentlyPlaying } from "./api/getCurrentlyPlaying"; +import { safeLaunchCommandInBackground } from "./helpers/safeCommandLauncher"; +import { seek } from "./api/seek"; + +export default async function Command() { + await setSpotifyClient(); + + const currentlyPlayingData = await getCurrentlyPlaying(); + const nothingIsPlaying = !currentlyPlayingData || !currentlyPlayingData.item; + + if (nothingIsPlaying) { + return await showHUD("Nothing is currently playing"); + } + + try { + const currentPositionSeconds = (currentlyPlayingData?.progress_ms || 0) / 1000; + await seek(Math.max(currentPositionSeconds - 15, 0)); + await showHUD("Skipped back 15 seconds"); + await safeLaunchCommandInBackground("current-track"); + } catch (error) { + await showHUD("Nothing is currently playing"); + } +} diff --git a/extensions/spotify-player/src/nowPlayingMenuBar.tsx b/extensions/spotify-player/src/nowPlayingMenuBar.tsx index 975c34d396a4b..959a9a1e0ae01 100644 --- a/extensions/spotify-player/src/nowPlayingMenuBar.tsx +++ b/extensions/spotify-player/src/nowPlayingMenuBar.tsx @@ -35,6 +35,7 @@ import { formatTitle } from "./helpers/formatTitle"; import { getErrorMessage } from "./helpers/getError"; import { useSpotifyAppData } from "./hooks/useSpotifyAppData"; +import { seek } from "./api/seek"; function NowPlayingMenuBarCommand({ launchType }: LaunchProps) { const { hideArtistName, maxTextLength, iconType } = getPreferenceValues(); @@ -190,6 +191,39 @@ function NowPlayingMenuBarCommand({ launchType }: LaunchProps) { const showName = show.name; title = formatTitle({ name, artistName: showName, hideArtistName, maxTextLength }); coverImageUrl = show.images.slice(-1)[0]?.url || ""; + + menuItems = ( + <> + { + try { + const currentPositionSeconds = (currentlyPlayingData?.progress_ms || 0) / 1000; + await seek(currentPositionSeconds + 15); + await currentlyPlayingRevalidate(); + } catch (err) { + const error = getErrorMessage(err); + showHUD(error); + } + }} + /> + { + try { + const currentPositionSeconds = (currentlyPlayingData?.progress_ms || 0) / 1000; + await seek(currentPositionSeconds - 15); + await currentlyPlayingRevalidate(); + } catch (err) { + const error = getErrorMessage(err); + showHUD(error); + } + }} + /> + + ); } return ( diff --git a/extensions/spotify-player/src/skip15.ts b/extensions/spotify-player/src/skip15.ts new file mode 100644 index 0000000000000..c753dcda91cd1 --- /dev/null +++ b/extensions/spotify-player/src/skip15.ts @@ -0,0 +1,25 @@ +import { showHUD } from "@raycast/api"; +import { setSpotifyClient } from "./helpers/withSpotifyClient"; +import { getCurrentlyPlaying } from "./api/getCurrentlyPlaying"; +import { safeLaunchCommandInBackground } from "./helpers/safeCommandLauncher"; +import { seek } from "./api/seek"; + +export default async function Command() { + await setSpotifyClient(); + + const currentlyPlayingData = await getCurrentlyPlaying(); + const nothingIsPlaying = !currentlyPlayingData || !currentlyPlayingData.item; + + if (nothingIsPlaying) { + return await showHUD("Nothing is currently playing"); + } + + try { + const currentPositionSeconds = (currentlyPlayingData?.progress_ms || 0) / 1000; + await seek(currentPositionSeconds + 15); + await showHUD("Skipped ahead 15 seconds"); + await safeLaunchCommandInBackground("current-track"); + } catch (error) { + await showHUD("Nothing is currently playing"); + } +} From 1b9935f6a0f26bcd38c225967bff614a4b49184b Mon Sep 17 00:00:00 2001 From: raycastbot Date: Wed, 19 Feb 2025 14:59:29 +0000 Subject: [PATCH 02/14] Docs: update for the new API release --- docs/.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/.config.json b/docs/.config.json index 75ed28fc9164c..c2a1515792517 100644 --- a/docs/.config.json +++ b/docs/.config.json @@ -1,3 +1,3 @@ { - "version": "1.91.2" + "version": "1.92.0" } From 2bfe38e0e31965297f4c515ffae8afc247f0ae89 Mon Sep 17 00:00:00 2001 From: raycastbot Date: Wed, 19 Feb 2025 15:03:20 +0000 Subject: [PATCH 03/14] Update CODEOWNERs --- .github/CODEOWNERS | 2 +- .github/raycast2github.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c550c6deff1ae..6a0ece6605a08 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1556,7 +1556,7 @@ /extensions/sportssync @daniyalmaster693 /extensions/spotify-beta @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon /extensions/spotify-controls @thomaspaulmann @altrdev @ron-myers @sandypockets @Kenan7 @dmacdermott @pernielsentikaer @yansq @amureki -/extensions/spotify-player @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon @pernielsentikaer @stevensd2m @erics118 @hjoelh @hobhouse @jatindotdev @the-devbear @rfaccio @badta5te @andyburris @thomaslombart @rhesamu @mpatel283 @LitoMore @EnneEmme +/extensions/spotify-player @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon @pernielsentikaer @stevensd2m @erics118 @hjoelh @hobhouse @jatindotdev @the-devbear @rfaccio @badta5te @andyburris @thomaslombart @rhesamu @mpatel283 @LitoMore @EnneEmme @lineville /extensions/spring-initializr @danvega /extensions/spryker-docs @DinisEsteves /extensions/sql-format @tonngw @jfkisafk diff --git a/.github/raycast2github.json b/.github/raycast2github.json index afdbe59a70b5b..711f2579ad1d0 100644 --- a/.github/raycast2github.json +++ b/.github/raycast2github.json @@ -1838,5 +1838,6 @@ "dziad": "tborychowski", "mattstone": "nandastone", "britown": "bkuzmanoski", - "joeynotjoe_2": "joeynotjoe" + "joeynotjoe_2": "joeynotjoe", + "lineville": "lineville" } \ No newline at end of file From 0f6ff7d0531e89e51a40974ab77644c9cb49918e Mon Sep 17 00:00:00 2001 From: raycastbot Date: Thu, 20 Feb 2025 10:07:41 +0000 Subject: [PATCH 04/14] Docs: update for the new API release --- docs/.config.json | 2 +- docs/examples/doppler.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/.config.json b/docs/.config.json index c2a1515792517..bc8ea9ec2553e 100644 --- a/docs/.config.json +++ b/docs/.config.json @@ -1,3 +1,3 @@ { - "version": "1.92.0" + "version": "1.92.1" } diff --git a/docs/examples/doppler.md b/docs/examples/doppler.md index 90f7b1278cad1..e893e884f5360 100644 --- a/docs/examples/doppler.md +++ b/docs/examples/doppler.md @@ -84,11 +84,11 @@ function ShareSecretAction() { await Clipboard.copy((body as any).authenticated_url); - toast.style = Feedback.Toast.Style.Success; + toast.style = Toast.Style.Success; toast.title = "Shared secret"; toast.message = "Copied link to clipboard"; } catch (error) { - toast.style = Feedback.Toast.Style.Failure; + toast.style = Toast.Style.Failure; toast.title = "Failed sharing secret"; toast.message = String(error); } From f10c4edbb993ac8a552eb0d84fb1f7df9a2e0538 Mon Sep 17 00:00:00 2001 From: Alex Sherwood <10284831+AlexIsMaking@users.noreply.github.com> Date: Thu, 20 Feb 2025 11:50:13 +0000 Subject: [PATCH 05/14] Update toggl-track extension (#16844) * Update toggl-track extension - Add ability to update time entry start and stop date - Initial commit * Change format of default dates * Set start time action for running time entry * Update toggl-track extension - Set start time action for running time entry - Set start time action for running time entry * Reorder time entry accessories --- extensions/toggl-track/CHANGELOG.md | 5 ++ extensions/toggl-track/package.json | 3 +- extensions/toggl-track/project-outline.md | 73 +++++++++++++++++++ .../src/components/RunningTimeEntry.tsx | 17 ++++- .../src/components/UpdateTimeEntryForm.tsx | 23 ++++-- .../toggl-track/src/hooks/useCurrentTime.ts | 15 +++- extensions/toggl-track/src/index.tsx | 2 +- extensions/toggl-track/src/menuBar.tsx | 2 +- 8 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 extensions/toggl-track/project-outline.md diff --git a/extensions/toggl-track/CHANGELOG.md b/extensions/toggl-track/CHANGELOG.md index 364250e78f7c0..710ff2b7044e1 100644 --- a/extensions/toggl-track/CHANGELOG.md +++ b/extensions/toggl-track/CHANGELOG.md @@ -1,5 +1,10 @@ # Toggl Track Changelog +## [New Feature] - 2025-02-05 + +- Add ability to update time entry start and stop date +- Add ability to change the start time for a running time entry + ## [New Feature] - 2025-12-12 - Add shortcut to "Create Similar Time Entry" diff --git a/extensions/toggl-track/package.json b/extensions/toggl-track/package.json index 647a1e032acba..25f2dda0fd295 100644 --- a/extensions/toggl-track/package.json +++ b/extensions/toggl-track/package.json @@ -16,7 +16,8 @@ "michaelfaisst", "teziovsky", "lukebars", - "AlanHuang" + "AlanHuang", + "alexs" ], "license": "MIT", "commands": [ diff --git a/extensions/toggl-track/project-outline.md b/extensions/toggl-track/project-outline.md new file mode 100644 index 0000000000000..55ee3728bb4f1 --- /dev/null +++ b/extensions/toggl-track/project-outline.md @@ -0,0 +1,73 @@ +## Stack + +--- + +- Vercel, using the pages app - Client and server +- Inngest - background jobs +- Supabase - database, for storing user data and translation data + +## Constraints + +--- + +### Inngest + +- Number of runs used, [limit for the free plan is 50k](https://www.inngest.com/pricing) + +### Vercel + +- [13.3 minutes function execution duration](https://vercel.com/docs/functions/configuring-functions/duration#duration-limits) +- [4.5mb request body size](https://vercel.com/docs/functions/limitations#request-body-size) + +### Notion + +- 3 requests per second +- [100 elements per block (paragraph)](https://developers.notion.com/reference/request-limits#limits-for-property-values) +- [2,000 characters per rich text object (element in paragraph)](https://developers.notion.com/reference/request-limits#limits-for-property-values) + +## Optimisations + +--- + +### Google Translate + +- Translate as much content as possible in each request e.g. as many blocks from a page as possible or all database properties (increases the risk of errors) +- Every input is an array of text + +## Design + +--- + +### Supabase + +- Store the IDs of all blocks that have been counted in Supabase, along with their from and to language, type, ~~block_count (for databases),~~ has_child_blocks (for pages), parent_id, ignore (used when user has changed app’s access or set manually, when requested) and their status. + - Statuses are pending, complete, error + - Types are database, database_page (for page titles and properties), page (for page titles) and page_block +- Retrieve those blocks in batches and keep processing them until all translations have been made +- If a user requests a new translation, blocks that have already been translated, with the same from - to languages, should not be translated again +- _There’s no need to link blocks to a translation job. Each request can simply fetch pending translations_ + +### App + +- Display a count of blocks counted vs blocks limit (from credits), on the dashboard +- Display a count of blocks to translate vs translated blocks, on the dashboard + +## Process + +--- + +All block inserts / updates are `upsert` requests + +- Fetch databases from workspace + - Database title = 1 block + - Each property (including drop down properties) = 1 block +- Check whether blocks have already been translated, then store database and property blocks in Supabase +- Fetch pages from the workspace, in batches of 100. + - Page title = 1 block + - Each property’s contents = 1 block +- Check whether page has block children (with `page_size = 1`, to speed up the request) +- Check whether blocks have already been translated, then store page and property blocks in Supabase +- For pages with block children, fetch the number of blocks from each of those pages, in batches of 10 +- Check whether blocks have already been translated, then store blocks in Supabase + +- Translate the database title and its properties, including dropdown options, in one go diff --git a/extensions/toggl-track/src/components/RunningTimeEntry.tsx b/extensions/toggl-track/src/components/RunningTimeEntry.tsx index f1d175fd19d20..df9ba9ead3692 100644 --- a/extensions/toggl-track/src/components/RunningTimeEntry.tsx +++ b/extensions/toggl-track/src/components/RunningTimeEntry.tsx @@ -1,7 +1,7 @@ import { Action, ActionPanel, Icon, List } from "@raycast/api"; import dayjs from "dayjs"; -import { TimeEntry, TimeEntryMetaData } from "@/api"; +import { TimeEntry, TimeEntryMetaData, updateTimeEntry } from "@/api"; import { useCurrentTime } from "@/hooks/useCurrentTime"; import { useTimeEntryActions } from "@/hooks/useTimeEntryActions"; @@ -16,7 +16,7 @@ function RunningTimeEntry({ revalidateRunningTimeEntry, revalidateTimeEntries, }: RunningTimeEntryProps) { - const currentTime = useCurrentTime(); + const { currentTime, setCurrentTime } = useCurrentTime(); const { stopRunningTimeEntry } = useTimeEntryActions(revalidateRunningTimeEntry, revalidateTimeEntries); @@ -46,6 +46,19 @@ function RunningTimeEntry({ onSubmit={() => stopRunningTimeEntry(runningTimeEntry)} title="Stop Time Entry" /> + { + if (date) { + await updateTimeEntry(runningTimeEntry.workspace_id, runningTimeEntry.id, { + start: date.toISOString(), + }); + revalidateRunningTimeEntry(); + setCurrentTime(dayjs()); + } + }} + /> } /> diff --git a/extensions/toggl-track/src/components/UpdateTimeEntryForm.tsx b/extensions/toggl-track/src/components/UpdateTimeEntryForm.tsx index 58ea56bb3e161..2708cb10a04a3 100644 --- a/extensions/toggl-track/src/components/UpdateTimeEntryForm.tsx +++ b/extensions/toggl-track/src/components/UpdateTimeEntryForm.tsx @@ -33,6 +33,10 @@ function UpdateTimeEntryForm({ timeEntry, revalidateTimeEntries }: UpdateTimeEnt const [billable, setBillable] = useState(timeEntry.billable); const [taskSearch, setTaskSearch] = useState(""); + const defaultStartDate = timeEntry.start ? new Date(timeEntry.start) : null; + const defaultEndDate = timeEntry.stop ? new Date(timeEntry.stop) : null; + const [startDate, setStartDate] = useState(defaultStartDate); + const [endDate, setEndDate] = useState(defaultEndDate); async function handleSubmit(values: { description: string; billable?: boolean }) { try { @@ -43,6 +47,8 @@ function UpdateTimeEntryForm({ timeEntry, revalidateTimeEntries }: UpdateTimeEnt billable: values.billable, project_id: selectedProject?.id, task_id: selectedTask?.id, + start: startDate?.toISOString(), + stop: endDate?.toISOString(), tags: selectedTags, }); @@ -127,10 +133,16 @@ function UpdateTimeEntryForm({ timeEntry, revalidateTimeEntries }: UpdateTimeEnt > + + + + + + setSelectedClient(clientId === "-1" ? undefined : clients.find((client) => client.id === parseInt(clientId))) } @@ -148,7 +160,7 @@ function UpdateTimeEntryForm({ timeEntry, revalidateTimeEntries }: UpdateTimeEnt {!isLoadingProjects && ( @@ -170,9 +182,8 @@ function UpdateTimeEntryForm({ timeEntry, revalidateTimeEntries }: UpdateTimeEnt setTaskSearch("")} > @@ -188,7 +199,9 @@ function UpdateTimeEntryForm({ timeEntry, revalidateTimeEntries }: UpdateTimeEnt )} - {selectedProject?.billable && } + {selectedProject?.billable && ( + + )} {tags diff --git a/extensions/toggl-track/src/hooks/useCurrentTime.ts b/extensions/toggl-track/src/hooks/useCurrentTime.ts index bd397810570f5..4c790037298b8 100644 --- a/extensions/toggl-track/src/hooks/useCurrentTime.ts +++ b/extensions/toggl-track/src/hooks/useCurrentTime.ts @@ -1,8 +1,15 @@ import dayjs from "dayjs"; +import type { Dayjs } from "dayjs"; import { useEffect, useState } from "react"; -export function useCurrentTime() { +interface CurrentTimeHook { + currentTime: Dayjs; + setCurrentTime: (time: Dayjs) => void; +} + +export function useCurrentTime(): CurrentTimeHook { const [currentTime, setCurrentTime] = useState(dayjs()); + useEffect(() => { const intervalId = setInterval(() => { setCurrentTime(dayjs()); @@ -12,5 +19,9 @@ export function useCurrentTime() { clearInterval(intervalId); }; }, []); - return currentTime; + + return { + currentTime, + setCurrentTime, + }; } diff --git a/extensions/toggl-track/src/index.tsx b/extensions/toggl-track/src/index.tsx index 4a8ef6968f475..f2890c67e5f79 100644 --- a/extensions/toggl-track/src/index.tsx +++ b/extensions/toggl-track/src/index.tsx @@ -74,9 +74,9 @@ function ListView() { title={timeEntry.description || "No description"} subtitle={(timeEntry.client_name ? timeEntry.client_name + " | " : "") + (timeEntry.project_name ?? "")} accessories={[ - { text: formatSeconds(timeEntry.duration) }, ...timeEntry.tags.map((tag) => ({ tag })), timeEntry.billable ? { tag: { value: "$" } } : {}, + { text: formatSeconds(timeEntry.duration) }, ]} icon={{ source: Icon.Circle, tintColor: timeEntry.project_color }} actions={ diff --git a/extensions/toggl-track/src/menuBar.tsx b/extensions/toggl-track/src/menuBar.tsx index cd7e10422662d..0b00a9e29ed9d 100644 --- a/extensions/toggl-track/src/menuBar.tsx +++ b/extensions/toggl-track/src/menuBar.tsx @@ -26,7 +26,7 @@ export default function Command() { revalidateRunningTimeEntry, revalidateTimeEntries, ); - const currentTime = useCurrentTime(); + const { currentTime } = useCurrentTime(); const runningEntry = runningTimeEntry; const currentDuration = runningEntry ? dayjs.duration(dayjs(currentTime).diff(runningEntry.start)) : undefined; From 2211ae91b5279279cf44826072f9a409d9414a94 Mon Sep 17 00:00:00 2001 From: raycastbot Date: Thu, 20 Feb 2025 11:53:48 +0000 Subject: [PATCH 06/14] Update CODEOWNERs --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6a0ece6605a08..334492dccdb5d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1693,7 +1693,7 @@ /extensions/to-streamshare @0PandaDEV @bkuzmanoski /extensions/todo-list @maggie-j-liu @joshkorol @madza91 @bkeys818 @pernielsentikaer @telmen @ridemountainpig /extensions/todoist @thomaslombart @AnishDe12020 @kud @casassg @Princeyadav05 @jfkisafk @ridemountainpig @kcole93 @RobErskine -/extensions/toggl-track @franzwilhelm @bkeys818 @michaelfaisst @teziovsky @lukebars @tangerine1202 +/extensions/toggl-track @franzwilhelm @bkeys818 @michaelfaisst @teziovsky @lukebars @tangerine1202 @AlexIsMaking /extensions/toggle-desktop-visibility @Haojen @VatsalSy /extensions/toggle-fn @elonwoo @pernielsentikaer /extensions/toggle-grayscale @zcsabbagh From ae729eea7d5a431ab0df1f79a1dc8fce5189e8ed Mon Sep 17 00:00:00 2001 From: Jagadeesh K Date: Thu, 20 Feb 2025 20:37:30 +0530 Subject: [PATCH 07/14] [Todoist] - Added Manual Sort Option - #16646 (#17073) * feat: Add Manual sorting option * chore: Add changelog * fix: username * Review * Update CHANGELOG.md and optimise images --------- Co-authored-by: Thomas Lombart Co-authored-by: raycastbot --- extensions/todoist/CHANGELOG.md | 4 ++++ extensions/todoist/package.json | 3 ++- extensions/todoist/src/helpers/sortBy.ts | 4 ++++ extensions/todoist/src/hooks/useViewTasks.ts | 3 ++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/extensions/todoist/CHANGELOG.md b/extensions/todoist/CHANGELOG.md index 4ba8715007a0d..076d58fde984a 100644 --- a/extensions/todoist/CHANGELOG.md +++ b/extensions/todoist/CHANGELOG.md @@ -1,5 +1,9 @@ # Todoist Changelog +## [Fix Default Sorting] - 2025-02-20 + +Change the default sorting to align with the task order in Todoist. + ## [Add time format preference from Todoist preferences] - 2025-02-17 - Raycast now pulls your preferred time format preference from the Todoist user account's settings and then uses that when displaying time diff --git a/extensions/todoist/package.json b/extensions/todoist/package.json index 4c82e126f46cb..231d4b2c98068 100644 --- a/extensions/todoist/package.json +++ b/extensions/todoist/package.json @@ -19,7 +19,8 @@ "stelo", "ridemountainpig", "kcole93", - "Rob" + "Rob", + "jagadeesh_k" ], "commands": [ { diff --git a/extensions/todoist/src/helpers/sortBy.ts b/extensions/todoist/src/helpers/sortBy.ts index 092b25cad729d..3c7cd13cd86b2 100644 --- a/extensions/todoist/src/helpers/sortBy.ts +++ b/extensions/todoist/src/helpers/sortBy.ts @@ -53,6 +53,10 @@ export function sortByName(a: Task, b: Task): number { return a.content.localeCompare(b.content); } +export function sortByDefault(a: Task, b: Task): number { + return a.child_order - b.child_order; +} + export function sortByAssignee(collaborators: Collaborator[], a: Task, b: Task): number { const aAssignee = a.responsible_uid ? collaborators.find((c) => c.id === a.responsible_uid) : null; const bAssignee = b.responsible_uid ? collaborators.find((c) => c.id === b.responsible_uid) : null; diff --git a/extensions/todoist/src/hooks/useViewTasks.ts b/extensions/todoist/src/hooks/useViewTasks.ts index d42dd72972dac..5aa0381532cc0 100644 --- a/extensions/todoist/src/hooks/useViewTasks.ts +++ b/extensions/todoist/src/hooks/useViewTasks.ts @@ -27,6 +27,7 @@ import { sortByName, sortByPriority, sortByProject, + sortByDefault, } from "../helpers/sortBy"; type ViewProp = { @@ -58,7 +59,7 @@ export default function useViewTasks(name: string, { tasks, optionsToExclude, da const [orderBy, setOrderBy] = useCachedState(name + "orderby", "asc"); const { sortByProp, sortedTasks, orderByProp } = useMemo(() => { - const sortedTasks = [...tasks]; + const sortedTasks = [...tasks].sort(sortByDefault); switch (sortBy) { case "name": From 9ea50374d03d76de752326743909815702c84c10 Mon Sep 17 00:00:00 2001 From: raycastbot Date: Thu, 20 Feb 2025 15:12:30 +0000 Subject: [PATCH 08/14] Update CODEOWNERs --- .github/CODEOWNERS | 2 +- .github/raycast2github.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 334492dccdb5d..e879ba2749625 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1692,7 +1692,7 @@ /extensions/tny @stayallive @stayallive /extensions/to-streamshare @0PandaDEV @bkuzmanoski /extensions/todo-list @maggie-j-liu @joshkorol @madza91 @bkeys818 @pernielsentikaer @telmen @ridemountainpig -/extensions/todoist @thomaslombart @AnishDe12020 @kud @casassg @Princeyadav05 @jfkisafk @ridemountainpig @kcole93 @RobErskine +/extensions/todoist @thomaslombart @AnishDe12020 @kud @casassg @Princeyadav05 @jfkisafk @ridemountainpig @kcole93 @RobErskine @jagadeesh-k-2802 /extensions/toggl-track @franzwilhelm @bkeys818 @michaelfaisst @teziovsky @lukebars @tangerine1202 @AlexIsMaking /extensions/toggle-desktop-visibility @Haojen @VatsalSy /extensions/toggle-fn @elonwoo @pernielsentikaer diff --git a/.github/raycast2github.json b/.github/raycast2github.json index 711f2579ad1d0..f2a599126d6a0 100644 --- a/.github/raycast2github.json +++ b/.github/raycast2github.json @@ -1839,5 +1839,6 @@ "mattstone": "nandastone", "britown": "bkuzmanoski", "joeynotjoe_2": "joeynotjoe", - "lineville": "lineville" + "lineville": "lineville", + "jagadeesh_k": "jagadeesh-k-2802" } \ No newline at end of file From 33af1f6eb728cc8d3e8b0d02f334576152e0e908 Mon Sep 17 00:00:00 2001 From: Daniel Andersson Date: Thu, 20 Feb 2025 16:34:29 +0100 Subject: [PATCH 09/14] feat: Add Copy Embed Code Command to Spotify Player (#17116) * feat: Add Copy Embed Code Command to Spotify Player * style: apply linting fixes to copyEmbed command * update command description and adress review comments * Update CHANGELOG.md and optimise images --------- Co-authored-by: Thomas Lombart Co-authored-by: raycastbot --- extensions/spotify-player/CHANGELOG.md | 4 ++++ extensions/spotify-player/package.json | 11 +++++++++- extensions/spotify-player/src/copyEmbed.ts | 24 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 extensions/spotify-player/src/copyEmbed.ts diff --git a/extensions/spotify-player/CHANGELOG.md b/extensions/spotify-player/CHANGELOG.md index 5dc0dfa2b1d8a..86f79a98af20a 100644 --- a/extensions/spotify-player/CHANGELOG.md +++ b/extensions/spotify-player/CHANGELOG.md @@ -1,5 +1,9 @@ # Spotify Player Changelog +## [Add Copy Embed Code Command] - 2025-02-20 + +- Added a new command to copy the iframe embed code for the currently playing song. + ## [Add "Skip 15 Seconds" and "Back 15 Seconds" commands] - 2025-02-18 - Added the ability to skip forward or back 15 seconds in the current episode. This adds two new commands as well as two new menu bar items which only show when an 'episode' is playing. diff --git a/extensions/spotify-player/package.json b/extensions/spotify-player/package.json index 57b365073badf..16290a6da8ebb 100644 --- a/extensions/spotify-player/package.json +++ b/extensions/spotify-player/package.json @@ -32,7 +32,8 @@ "themitpatel", "litomore", "enneemme", - "lineville" + "lineville", + "tsibog" ], "pastContributors": [ "bkeys818" @@ -445,6 +446,14 @@ "mode": "no-view", "disabledByDefault": true }, + { + "name": "copyEmbed", + "title": "Copy Embed Code", + "subtitle": "Spotify", + "description": "Copy the iframe embed code for the currently playing song or podcast episode.", + "mode": "no-view", + "disabledByDefault": true + }, { "name": "skip15", "title": "Skip 15 Seconds", diff --git a/extensions/spotify-player/src/copyEmbed.ts b/extensions/spotify-player/src/copyEmbed.ts new file mode 100644 index 0000000000000..ba5f9dc8b121e --- /dev/null +++ b/extensions/spotify-player/src/copyEmbed.ts @@ -0,0 +1,24 @@ +import { Clipboard, showHUD } from "@raycast/api"; +import { setSpotifyClient } from "./helpers/withSpotifyClient"; +import { getCurrentlyPlaying } from "./api/getCurrentlyPlaying"; + +export default async function Command() { + await setSpotifyClient(); + + const currentlyPlayingData = await getCurrentlyPlaying(); + const nothingIsPlaying = !currentlyPlayingData || !currentlyPlayingData.item; + + if (nothingIsPlaying) { + return await showHUD("Nothing is currently playing"); + } + + const external_urls = currentlyPlayingData.item.external_urls; + const spotifyUrl = external_urls?.spotify; + + const embedUrl = spotifyUrl?.replace("open.spotify.com/", "open.spotify.com/embed/"); + + const embedCode = ``; + + await Clipboard.copy(embedCode); + return showHUD("Copied embed code to clipboard"); +} From 90cfc9dadeaa5d7915652098febf07b8a06a51b5 Mon Sep 17 00:00:00 2001 From: Jagadeesh K Date: Thu, 20 Feb 2025 21:07:01 +0530 Subject: [PATCH 10/14] [Todoist] - Added Show Next Most Prioirity Task as Menu Bar Title - #16647 (#17100) * feat: Add Manual sorting option * chore: Add changelog * fix: username * feat: - Add new menubar option to show next first task as title * refactor: Revert sort code * fix: CI * fix: * Review * Update CHANGELOG.md and optimise images --------- Co-authored-by: Thomas Lombart Co-authored-by: raycastbot --- extensions/todoist/CHANGELOG.md | 4 ++++ extensions/todoist/package.json | 9 ++++++++- extensions/todoist/src/menu-bar.tsx | 15 +++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/extensions/todoist/CHANGELOG.md b/extensions/todoist/CHANGELOG.md index 076d58fde984a..fb25b60816f06 100644 --- a/extensions/todoist/CHANGELOG.md +++ b/extensions/todoist/CHANGELOG.md @@ -1,5 +1,9 @@ # Todoist Changelog +## [Add Next Task as Title in Menu Bar] - 2025-02-20 + +Added option to display the next upcoming task in the menu bar title when no task is selected. This can be enabled in preferences. + ## [Fix Default Sorting] - 2025-02-20 Change the default sorting to align with the task order in Todoist. diff --git a/extensions/todoist/package.json b/extensions/todoist/package.json index 231d4b2c98068..a61c311f0cad7 100644 --- a/extensions/todoist/package.json +++ b/extensions/todoist/package.json @@ -130,12 +130,19 @@ { "name": "hideMenuBarCount", "type": "checkbox", - "title": "Count", "label": "Hide menu bar count", "description": "When enabled, the number of tasks in the menu bar won't be shown.", "default": false, "required": false }, + { + "name": "showNextTask", + "type": "checkbox", + "label": "Show next task as title", + "description": "When enabled and no task is focused, displays your next upcoming task in the menu bar title", + "default": false, + "required": false + }, { "name": "view", "type": "dropdown", diff --git a/extensions/todoist/src/menu-bar.tsx b/extensions/todoist/src/menu-bar.tsx index 979852aec7b0b..5ded12bec64df 100644 --- a/extensions/todoist/src/menu-bar.tsx +++ b/extensions/todoist/src/menu-bar.tsx @@ -18,6 +18,7 @@ import MenuBarTask from "./components/MenubarTask"; import View from "./components/View"; import { getToday } from "./helpers/dates"; import { groupByDates } from "./helpers/groupBy"; +import { truncateMiddle } from "./helpers/menu-bar"; import { getTasksForTodayOrUpcomingView } from "./helpers/tasks"; import useFilterTasks from "./hooks/useFilterData"; import { useFocusedTask } from "./hooks/useFocusedTask"; @@ -30,7 +31,8 @@ function MenuBar(props: MenuBarProps) { // Don't perform a full sync if the command was launched from within another commands const { data, setData, isLoading } = useSyncData(!launchedFromWithinCommand); const { focusedTask, unfocusTask } = useFocusedTask(); - const { view, filter, upcomingDays, hideMenuBarCount } = getPreferenceValues(); + const { view, filter, upcomingDays, hideMenuBarCount, showNextTask, taskWidth } = + getPreferenceValues(); const { data: filterTasks, isLoading: isLoadingFilter } = useFilterTasks(view === "filter" ? filter : ""); const tasks = useMemo(() => { @@ -73,6 +75,15 @@ function MenuBar(props: MenuBarProps) { return removeMarkdown(focusedTask.content); } + if (showNextTask) { + const taskList = view !== "filter" ? tasks : filterTasks; + if (taskList && taskList.length > 0) { + const nextTask = [...taskList].sort((a, b) => a.child_order - b.child_order)[0]; + const content = truncateMiddle(nextTask.content, parseInt(taskWidth ?? "40")); + return removeMarkdown(content); + } + } + if (hideMenuBarCount) { return ""; } @@ -82,7 +93,7 @@ function MenuBar(props: MenuBarProps) { } else if (filterTasks) { return filterTasks.length > 0 ? filterTasks.length.toString() : "🎉"; } - }, [focusedTask, tasks, hideMenuBarCount, filterTasks, view]); + }, [focusedTask, tasks, hideMenuBarCount, filterTasks, view, showNextTask, taskWidth]); let taskView = tasks && ; if (view === "today") { From 27ee8984b1d9c0881c0da9e278f049e14686f920 Mon Sep 17 00:00:00 2001 From: Paul Arterburn Date: Thu, 20 Feb 2025 08:43:37 -0700 Subject: [PATCH 11/14] Option to show start date in Asana create form (#16960) * Option to show start date in Asana create form * adjust label * Run ray lint --fix * Review --------- Co-authored-by: Thomas Lombart --- extensions/asana/CHANGELOG.md | 8 ++++++-- extensions/asana/package.json | 16 ++++++++++++++-- .../asana/src/components/CreateTaskForm.tsx | 15 +++++++++++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/extensions/asana/CHANGELOG.md b/extensions/asana/CHANGELOG.md index 7571a8bfb8fc0..370e30a38b09b 100644 --- a/extensions/asana/CHANGELOG.md +++ b/extensions/asana/CHANGELOG.md @@ -1,6 +1,10 @@ # Asana Changelog -## [Added Copy Task Formatted URL command] - 2024-03-27 +## [Add option to hide the "Start Date" field] - 2025-02-12 + +- Add a preference to allow the user to hide the `Start Date` field in the `Create Task` command + +## [Add "Copy Task Formatted URL" action] - 2024-03-27 - Added a new task command - "Copy Task Formatted URL" @@ -18,7 +22,7 @@ - Remove Raycast signature preference from the `Create Task` command -## [Bugfix] - 2022-11-24 +## [Fix a bug] - 2022-11-24 Fixed an issue where the Asana extension would timeout when querying for projects in workspaces with a lot of projects. diff --git a/extensions/asana/package.json b/extensions/asana/package.json index 896cab22dd174..9d6707387db63 100644 --- a/extensions/asana/package.json +++ b/extensions/asana/package.json @@ -11,14 +11,26 @@ ], "owner": "raycast", "access": "public", - "categories": ["Productivity"], + "categories": [ + "Productivity" + ], "license": "MIT", "commands": [ { "name": "create-task", "title": "Create Task", "description": "Create and assign new tasks.", - "mode": "view" + "mode": "view", + "preferences": [ + { + "name": "showStartDate", + "type": "checkbox", + "label": "Show the \"Start Date\" field", + "description": "When enabled, the \"Start Date\" field will be shown in the \"Create Task\" command.", + "required": false, + "default": true + } + ] }, { "name": "my-tasks", diff --git a/extensions/asana/src/components/CreateTaskForm.tsx b/extensions/asana/src/components/CreateTaskForm.tsx index ea6f2251c7711..8b88cbe006ece 100644 --- a/extensions/asana/src/components/CreateTaskForm.tsx +++ b/extensions/asana/src/components/CreateTaskForm.tsx @@ -1,4 +1,14 @@ -import { Action, ActionPanel, Clipboard, Form, Icon, useNavigation, Toast, showToast } from "@raycast/api"; +import { + Action, + ActionPanel, + Clipboard, + Form, + Icon, + useNavigation, + Toast, + showToast, + getPreferenceValues, +} from "@raycast/api"; import { format } from "date-fns"; import { FormValidation, getAvatarIcon, useCachedState, useForm } from "@raycast/utils"; import { useMemo, useEffect } from "react"; @@ -122,6 +132,7 @@ export default function CreateTaskForm(props: { const hasCustomFields = customFields && customFields.length > 0; const selectedWorkspace = workspaces?.find((workspace) => values.workspace === workspace.gid); + const { showStartDate } = getPreferenceValues(); return (
- {selectedWorkspace?.is_organization ? ( + {selectedWorkspace?.is_organization && showStartDate ? ( ) : null} From ddc6aaa324d1fd4c14342ef5687ccfce61c9e7b9 Mon Sep 17 00:00:00 2001 From: raycastbot Date: Thu, 20 Feb 2025 15:43:59 +0000 Subject: [PATCH 12/14] Update CODEOWNERs --- .github/CODEOWNERS | 2 +- .github/raycast2github.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e879ba2749625..c4eea564babe9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1556,7 +1556,7 @@ /extensions/sportssync @daniyalmaster693 /extensions/spotify-beta @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon /extensions/spotify-controls @thomaspaulmann @altrdev @ron-myers @sandypockets @Kenan7 @dmacdermott @pernielsentikaer @yansq @amureki -/extensions/spotify-player @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon @pernielsentikaer @stevensd2m @erics118 @hjoelh @hobhouse @jatindotdev @the-devbear @rfaccio @badta5te @andyburris @thomaslombart @rhesamu @mpatel283 @LitoMore @EnneEmme @lineville +/extensions/spotify-player @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon @pernielsentikaer @stevensd2m @erics118 @hjoelh @hobhouse @jatindotdev @the-devbear @rfaccio @badta5te @andyburris @thomaslombart @rhesamu @mpatel283 @LitoMore @EnneEmme @lineville @tsibog /extensions/spring-initializr @danvega /extensions/spryker-docs @DinisEsteves /extensions/sql-format @tonngw @jfkisafk diff --git a/.github/raycast2github.json b/.github/raycast2github.json index f2a599126d6a0..d9a5ba1d652a6 100644 --- a/.github/raycast2github.json +++ b/.github/raycast2github.json @@ -1840,5 +1840,6 @@ "britown": "bkuzmanoski", "joeynotjoe_2": "joeynotjoe", "lineville": "lineville", - "jagadeesh_k": "jagadeesh-k-2802" + "jagadeesh_k": "jagadeesh-k-2802", + "tsibog": "tsibog" } \ No newline at end of file From 10dce249e67b28034554e17b8152966f7c66363a Mon Sep 17 00:00:00 2001 From: Viet Hung Date: Thu, 20 Feb 2025 23:22:16 +0700 Subject: [PATCH 13/14] [Spotify Playlist] Fix Missing Playlists in Add Playing Song to Playlist command (#16295) * Update spotify-player: fetch all playlist * Review * Update CHANGELOG.md and optimise images --------- Co-authored-by: Thomas Lombart Co-authored-by: raycastbot --- extensions/spotify-player/CHANGELOG.md | 4 ++ extensions/spotify-player/package.json | 3 +- .../spotify-player/src/api/getMyPlaylists.ts | 20 ++++++++-- .../spotify-player/src/helpers/spotify.api.ts | 38 +++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/extensions/spotify-player/CHANGELOG.md b/extensions/spotify-player/CHANGELOG.md index 86f79a98af20a..338c0cc241198 100644 --- a/extensions/spotify-player/CHANGELOG.md +++ b/extensions/spotify-player/CHANGELOG.md @@ -1,5 +1,9 @@ # Spotify Player Changelog +## [Fix Missing Playlists in Add Playing Song to Playlist command] - 2025-02-20 + +- Fixed an issue where some playlists were not appearing when users attempted to add a currently playing song to a playlist. + ## [Add Copy Embed Code Command] - 2025-02-20 - Added a new command to copy the iframe embed code for the currently playing song. diff --git a/extensions/spotify-player/package.json b/extensions/spotify-player/package.json index 16290a6da8ebb..e5d4ea8afb1ff 100644 --- a/extensions/spotify-player/package.json +++ b/extensions/spotify-player/package.json @@ -33,7 +33,8 @@ "litomore", "enneemme", "lineville", - "tsibog" + "tsibog", + "viethung0823" ], "pastContributors": [ "bkeys818" diff --git a/extensions/spotify-player/src/api/getMyPlaylists.ts b/extensions/spotify-player/src/api/getMyPlaylists.ts index 1a652b56de3b1..7466b01f00965 100644 --- a/extensions/spotify-player/src/api/getMyPlaylists.ts +++ b/extensions/spotify-player/src/api/getMyPlaylists.ts @@ -1,13 +1,27 @@ import { getErrorMessage } from "../helpers/getError"; import { getSpotifyClient } from "../helpers/withSpotifyClient"; -type GetMySavedAlbumsProps = { limit?: number }; +type GetUserPlaylistsProps = { limit?: number }; -export async function getMyPlaylists({ limit = 50 }: GetMySavedAlbumsProps = {}) { +export async function getMyPlaylists({ limit = 50 }: GetUserPlaylistsProps = {}) { const { spotifyClient } = getSpotifyClient(); + let response = null; + let nextUrl = null; try { - const response = await spotifyClient.getMePlaylists({ limit }); + response = await spotifyClient.getMePlaylists({ limit }); + nextUrl = response?.next; + + while (nextUrl) { + const nextResponse = await spotifyClient.getNext(nextUrl); + response = { + ...response, + ...nextResponse, + items: [...(response?.items ?? []), ...(nextResponse.items ?? [])], + }; + nextUrl = nextResponse?.next; + } + return response; } catch (err) { const error = getErrorMessage(err); diff --git a/extensions/spotify-player/src/helpers/spotify.api.ts b/extensions/spotify-player/src/helpers/spotify.api.ts index 14ec40dda3013..2b35747988979 100644 --- a/extensions/spotify-player/src/helpers/spotify.api.ts +++ b/extensions/spotify-player/src/helpers/spotify.api.ts @@ -5082,3 +5082,41 @@ export function getMeTopTracks( ), ); } +/** + * Get next page + * + */ +export function getNext( + nextUrl: string, + opts?: Oazapfts.RequestOpts, +) { + const url = nextUrl.replace(servers.server1, ""); + return oazapfts.ok( + oazapfts.fetchJson< + | { + status: 200; + data: PagingPlaylistObject; + } + | { + status: 401; + data: { + error: ErrorObject; + }; + } + | { + status: 403; + data: { + error: ErrorObject; + }; + } + | { + status: 429; + data: { + error: ErrorObject; + }; + } + >(url, { + ...opts, + }), + ); +} From d952187258a5cd7a504e36dddb11ce387a050168 Mon Sep 17 00:00:00 2001 From: raycastbot Date: Thu, 20 Feb 2025 16:26:15 +0000 Subject: [PATCH 14/14] Update CODEOWNERs --- .github/CODEOWNERS | 2 +- .github/raycast2github.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c4eea564babe9..5d74c86e45062 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1556,7 +1556,7 @@ /extensions/sportssync @daniyalmaster693 /extensions/spotify-beta @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon /extensions/spotify-controls @thomaspaulmann @altrdev @ron-myers @sandypockets @Kenan7 @dmacdermott @pernielsentikaer @yansq @amureki -/extensions/spotify-player @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon @pernielsentikaer @stevensd2m @erics118 @hjoelh @hobhouse @jatindotdev @the-devbear @rfaccio @badta5te @andyburris @thomaslombart @rhesamu @mpatel283 @LitoMore @EnneEmme @lineville @tsibog +/extensions/spotify-player @mattisssa @peduarte @sxn @dillionverma @andreaselia @stuart @tonka3000 @dancannon @pernielsentikaer @stevensd2m @erics118 @hjoelh @hobhouse @jatindotdev @the-devbear @rfaccio @badta5te @andyburris @thomaslombart @rhesamu @mpatel283 @LitoMore @EnneEmme @lineville @tsibog @viethung0823 /extensions/spring-initializr @danvega /extensions/spryker-docs @DinisEsteves /extensions/sql-format @tonngw @jfkisafk diff --git a/.github/raycast2github.json b/.github/raycast2github.json index d9a5ba1d652a6..ea028e96159cd 100644 --- a/.github/raycast2github.json +++ b/.github/raycast2github.json @@ -1841,5 +1841,6 @@ "joeynotjoe_2": "joeynotjoe", "lineville": "lineville", "jagadeesh_k": "jagadeesh-k-2802", - "tsibog": "tsibog" + "tsibog": "tsibog", + "viethung0823": "viethung0823" } \ No newline at end of file