feat: add slack-templated-message extension#17253
Conversation
|
Congratulations on your new Raycast extension! 🚀 Due to our current reduced availability, the initial review may take up to 10-15 business days Once the PR is approved and merged, the extension will be available on our Store. |
|
Hi 👋 Thanks for your contribution 🔥 Wouldn't it make sense to add this to this extension by @momme-rtf? This way, we can have one Slack extension with all the cool features |
|
Hi there! I did check out the existing extension, but I think mine should remain separate. In my view, the existing extension seems to function primarily as a simple adapter for Slack, whereas my extension focuses on eliminating the routine of typing the same messages to send to Slack every day. I believe having separate extensions with different purposes is easier to maintain than merging different functionalities into one extension. However, I understand the concern about having too many similar extensions in the store. I'd love to hear your thoughts on this. |
|
Thanks for the clarification, that makes sense 😊 @greptileai can you check this |
There was a problem hiding this comment.
PR Summary
This PR adds a new Slack Templated Message extension that enables users to create, manage, and send customizable message templates to Slack channels with variable substitution and thread reply support.
- The extension implements four main commands: Create Template, Send Message, Export Templates, and Import Templates with a clean UI and proper OAuth authentication
- Robust template management system in
src/lib/templates.tshandles storage, validation, and CRUD operations for message templates - Well-implemented variable substitution system in
src/lib/slack.tssupports {date}, {time}, and {user} variables in templates - Thread reply functionality includes sophisticated timestamp validation and normalization for proper Slack thread integration
- Shared components in
src/components/shared.tsxprovide reusable UI elements like ChannelDropdown and ThreadField across different commands
15 file(s) reviewed, 13 comment(s)
Edit PR Review Bot Settings | Greptile
| 1. Open Raycast and run `Send Slack Message` | ||
| 2. Select a template to use | ||
| 3. The message will be sent to the pre-configured channel with the variables automatically replaced | ||
| 4. Press `⌘ + K` to edit or delete the selected template |
There was a problem hiding this comment.
logic: The README mentions using ⌘ + K to edit/delete templates, but in send-message.tsx the shortcuts are ⌘ + E for edit and ⌘ + backspace for delete.
There was a problem hiding this comment.
We should use Keyboard.Shortcut.Common.Remove for delete
| const { token } = await getAccessToken(); | ||
| if (!token) return; | ||
| const client = new WebClient(token); | ||
| const allChannels = await fetchAllChannels(client); | ||
| setChannels(allChannels); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } finally { |
There was a problem hiding this comment.
style: Error handling only logs to console but doesn't show a user-facing error message. Consider using showFailureToast from @raycast/utils to provide feedback to the user when channel fetching fails.
| try { | ||
| // Initialize Slack client | ||
| const { token } = await getAccessToken(); | ||
| if (!token) { | ||
| throw new Error("Failed to get authentication credentials"); | ||
| } |
There was a problem hiding this comment.
style: Consider using showFailureToast from @raycast/utils instead of manually creating error toasts
| <List isLoading={isLoading}> | ||
| <List.Item | ||
| title={`Export ${templates.length} templates`} | ||
| subtitle={`Save to: ${DEFAULT_TEMPLATE_PATH}`} | ||
| actions={ | ||
| <ActionPanel> | ||
| <Action title="Export" onAction={handleExport} /> | ||
| </ActionPanel> | ||
| } | ||
| /> | ||
| </List> |
There was a problem hiding this comment.
style: Consider adding an empty state message when templates.length is 0 to improve user experience
| export async function writeTemplatesToFile(filePath: string, templates: SlackTemplate[]): Promise<void> { | ||
| await fs.writeFile(filePath, JSON.stringify(templates, null, 2)); | ||
| } |
There was a problem hiding this comment.
style: Missing error handling for file writing operation. This function should be wrapped in a try/catch block like other file operations in this module.
| const templates = await loadTemplates(); | ||
| const updatedTemplates = templates.map((t) => (t.name === originalName ? updatedTemplate : t)); | ||
| await saveTemplatesToFile(updatedTemplates); |
There was a problem hiding this comment.
style: Using loadTemplates() here could potentially show duplicate error toasts if there's an issue, since loadTemplates already shows a toast on error.
| // Validate channel selection | ||
| const selectedChannel = channels.find((c) => c.id === values.slackChannelId); | ||
| if (!selectedChannel) { | ||
| throw new Error("Selected channel not found"); |
There was a problem hiding this comment.
logic: Throwing an error here will cause an unhandled exception. Consider using showCustomToast instead and returning early.
|
Could you check the messages from the bot? |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
f08395b to
6c2af01
Compare
6c2af01 to
9c5bd8a
Compare
|
Thank you for your review! |
|
@greptileai please check again |
pernielsentikaer
left a comment
There was a problem hiding this comment.
The extension icon is not working well in both appearances; could you look into this? If you struggle to do so, then you can use our generator
There was a problem hiding this comment.
PR Summary
(updates since last review)
This PR continues to evolve the Slack Templated Message extension with several important improvements to error handling and user experience.
- Improved error handling across the extension by replacing thrown errors with
showFailureToastfrom@raycast/utilsfor better user feedback - Added proper empty state handling in
export-templates.tsxwithisLoadingflag to prevent flicker - Simplified
mergeTemplatesfunction inimport-templates.tsxby removing unnecessary async keyword and string interpolation - Strengthened template validation in
templates.tswith explicit array type checking for imported templates
The changes focus on making the extension more robust and user-friendly while maintaining clean code practices.
8 file(s) reviewed, 10 comment(s)
Edit PR Review Bot Settings | Greptile
| .catch(async (error) => { | ||
| await handleOperationError(error, "export"); | ||
| }) |
There was a problem hiding this comment.
style: Consider using showFailureToast from @raycast/utils to simplify error handling
| - `{date}` - Current date (YYYY-MM-DD) | ||
| - `{time}` - Current time (HH:MM) | ||
| - `{user}` - Your Slack username |
There was a problem hiding this comment.
style: Consider adding examples for the date/time/user variables to make the format clearer, e.g. {date} - Current date (YYYY-MM-DD, e.g. 2024-03-04)
| // Validate channel selection | ||
| const selectedChannel = channels.find((c) => c.id === values.slackChannelId); | ||
| if (!selectedChannel) { | ||
| throw new Error("Selected channel not found"); | ||
| } |
There was a problem hiding this comment.
logic: Channel validation should happen before thread validation to fail fast. Move this check before line 67.
| <Form.TextField id="name" title="Template Name" placeholder="Enter the name of the template" /> | ||
| <Form.TextArea id="message" title="Message" placeholder="Enter your message template" /> | ||
| <ChannelDropdown channels={channels} /> |
There was a problem hiding this comment.
style: Consider adding maxLength constraints to name and message fields to prevent oversized templates
| value={filePath} | ||
| onChange={setFilePath} | ||
| /> | ||
| <Form.Checkbox id="overwrite" label="Update duplicate Items" defaultValue={false} /> |
There was a problem hiding this comment.
style: Inconsistent capitalization in label - 'Items' should be lowercase to match UI style
| const templates = await loadTemplates(); | ||
| const updatedTemplates = templates.filter((t) => t.name !== templateName); |
There was a problem hiding this comment.
style: Using loadTemplates() here but loadTemplatesFromFile() in updateTemplate() - should be consistent across similar operations
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
pernielsentikaer
left a comment
There was a problem hiding this comment.
Hi 👋
Looks good to me, approved 🔥
|
Published to the Raycast Store: |
|
🎉 🎉 🎉 Such a great contribution deserves a reward, but unfortunately we couldn't find your Raycast account based on your GitHub username (@koh-sh). |
|
@pernielsentikaer |
Description
A Raycast Extension for sending messages to Slack channels using customizable templates.
[Features]
Screencast
Screen.Recording.2025-02-23.at.18.08.12.mov
Checklist
npm run buildand tested this distribution build in Raycastassetsfolder are used by the extension itselfREADMEare placed outside of themetadatafolder