Skip to content

Commit 7c8f65d

Browse files
feat: add skip button to queued posts and display version in header
- Add skip button to QueuedPostCard for dismissing posts before AI analysis - Skipped queued posts appear in Skipped tab with "Pre-Skipped" badge - Add skippedBeforeAnalysis flag to MatchedPostWithScore type - Add SKIP_QUEUED_POST message and handler in background service worker - Display extension version next to ReplyQueue title in header
1 parent 62d4c34 commit 7c8f65d

7 files changed

Lines changed: 139 additions & 2 deletions

File tree

src/background/index.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
isCachedFeedValid,
3131
addEvaluatedPostIds,
3232
getEvaluatedPostIds,
33+
skipQueuedPost,
3334
} from '../shared/storage';
3435
import {
3536
DEFAULT_MATCHING_PREFERENCES,
@@ -744,6 +745,28 @@ async function handleRequestHostPermission(message: ExtensionMessage): Promise<M
744745
}
745746
}
746747

748+
/**
749+
* Handle SKIP_QUEUED_POST message
750+
* Skips a queued post before AI analysis
751+
*/
752+
async function handleSkipQueuedPost(message: ExtensionMessage): Promise<MessageResponse> {
753+
const { postId, platform } = message as { postId: string; platform: string };
754+
755+
if (!postId || !platform) {
756+
return { success: false, error: 'Post ID and platform are required' };
757+
}
758+
759+
try {
760+
await skipQueuedPost(postId, platform);
761+
console.log(`${LOG_PREFIX} Skipped queued post ${postId} from ${platform}`);
762+
return { success: true };
763+
} catch (error) {
764+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
765+
console.error(`${LOG_PREFIX} Error skipping queued post:`, error);
766+
return { success: false, error: errorMessage };
767+
}
768+
}
769+
747770
/**
748771
* Main message handler
749772
*/
@@ -805,6 +828,9 @@ chrome.runtime.onMessage.addListener(
805828
case 'HEAT_CHECK_POSTS':
806829
return handleHeatCheckPosts();
807830

831+
case 'SKIP_QUEUED_POST':
832+
return handleSkipQueuedPost(message);
833+
808834
case 'CHECK_HOST_PERMISSION':
809835
return handleCheckHostPermission(message);
810836

src/shared/messages.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export type MessageType =
2727
| 'GENERATE_SUGGESTIONS'
2828
| 'REGENERATE_SUGGESTIONS'
2929
| 'HEAT_CHECK_POSTS'
30+
// Queue management
31+
| 'SKIP_QUEUED_POST'
3032
// Permission messages
3133
| 'REQUEST_HOST_PERMISSION'
3234
| 'CHECK_HOST_PERMISSION';
@@ -175,6 +177,19 @@ export interface HeatCheckPostsMessage extends BaseMessage {
175177
type: 'HEAT_CHECK_POSTS';
176178
}
177179

180+
// ============================================================
181+
// Queue management messages
182+
// ============================================================
183+
184+
/**
185+
* Skip a queued post before AI analysis
186+
*/
187+
export interface SkipQueuedPostMessage extends BaseMessage {
188+
type: 'SKIP_QUEUED_POST';
189+
postId: string;
190+
platform: string;
191+
}
192+
178193
// ============================================================
179194
// Permission messages
180195
// ============================================================
@@ -218,6 +233,7 @@ export type ExtensionMessage =
218233
| GenerateSuggestionsMessage
219234
| RegenerateSuggestionsMessage
220235
| HeatCheckPostsMessage
236+
| SkipQueuedPostMessage
221237
| RequestHostPermissionMessage
222238
| CheckHostPermissionMessage;
223239

src/shared/storage.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,44 @@ export async function clearExampleComments(): Promise<void> {
605605
}
606606
}
607607

608+
// ============================================================
609+
// Skip queued post (before AI analysis)
610+
// ============================================================
611+
612+
/**
613+
* Skip a queued post before AI analysis
614+
* Creates a synthetic MatchedPostWithScore with status 'skipped' and skippedBeforeAnalysis flag
615+
*/
616+
export async function skipQueuedPost(postId: string, platform: string): Promise<void> {
617+
// Find post in extractedPosts
618+
const extractedPosts = await getExtractedPosts();
619+
const post = extractedPosts.find((p) => p.id === postId && p.platform === platform);
620+
621+
if (!post) {
622+
throw new Error('Post not found in queue');
623+
}
624+
625+
// Create synthetic MatchedPostWithScore
626+
const skippedMatch: MatchedPostWithScore = {
627+
post,
628+
score: 0,
629+
matchedKeywords: [],
630+
matchReason: 'Skipped before AI analysis',
631+
matchedAt: Date.now(),
632+
status: 'skipped',
633+
skippedBeforeAnalysis: true,
634+
};
635+
636+
// Add to matchedPostsWithScore
637+
const matchedPosts = await getMatchedPostsWithScore();
638+
matchedPosts.push(skippedMatch);
639+
await saveMatchedPostsWithScore(matchedPosts);
640+
641+
// Add to evaluatedPostIds so it doesn't show in queue
642+
const key = `${platform}:${postId}`;
643+
await addEvaluatedPostIds([key]);
644+
}
645+
608646
// ============================================================
609647
// Export storage object
610648
// ============================================================
@@ -636,6 +674,8 @@ export const storage = {
636674
saveMatchedPostsWithScore,
637675
updateMatchedPostStatus,
638676
clearMatchedPostsWithScore,
677+
// Skip queued post
678+
skipQueuedPost,
639679
// Evaluated post IDs
640680
getEvaluatedPostIds,
641681
saveEvaluatedPostIds,

src/shared/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ export interface MatchedPostWithScore {
209209
draftReply?: string;
210210
/** Heat check result (tone/sentiment analysis) */
211211
heatCheck?: HeatCheckResult;
212+
/** Flag indicating post was skipped before AI analysis */
213+
skippedBeforeAnalysis?: boolean;
212214
}
213215

214216
/**

src/sidepanel/components/PostCard.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ const hiddenSuggestionsCount = computed(() => {
173173
<span class="rounded-full px-2 py-0.5 text-xs font-medium" :class="statusBadge.class">
174174
{{ statusBadge.text }}
175175
</span>
176+
<span
177+
v-if="match.skippedBeforeAnalysis"
178+
class="rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-500"
179+
>
180+
Pre-Skipped
181+
</span>
176182
</div>
177183
<div class="flex items-center gap-1.5">
178184
<!-- Heat Check Badge -->

src/sidepanel/components/QueuedPostCard.vue

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const props = defineProps<{
1010
const emit = defineEmits<{
1111
(e: 'open', postId: string, platform: string): void;
1212
(e: 'jumpToPost', postId: string, platform: string): void;
13+
(e: 'skip', postId: string, platform: string): void;
1314
}>();
1415
1516
const isJumping = ref(false);
@@ -53,6 +54,10 @@ function handleJumpToPost() {
5354
isJumping.value = false;
5455
}, 1500);
5556
}
57+
58+
function handleSkip() {
59+
emit('skip', props.post.id, props.post.platform);
60+
}
5661
</script>
5762

5863
<template>
@@ -98,6 +103,14 @@ function handleJumpToPost() {
98103

99104
<!-- Footer -->
100105
<div class="flex items-center justify-end gap-2 border-t border-gray-100 pt-3">
106+
<button
107+
type="button"
108+
class="rounded px-2 py-1 text-xs text-gray-500 hover:bg-gray-100"
109+
title="Skip this post"
110+
@click="handleSkip"
111+
>
112+
Skip
113+
</button>
101114
<button
102115
type="button"
103116
class="flex items-center gap-1 rounded px-2 py-1 text-xs text-gray-500 hover:bg-gray-100"

src/sidepanel/views/MainView.vue

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { ref } from 'vue';
2+
import { ref, computed } from 'vue';
33
import { useAppState } from '../composables/useAppState';
44
import { usePosts, type PostFilter } from '../composables/usePosts';
55
import { useConfig } from '../composables/useConfig';
@@ -43,6 +43,14 @@ const {
4343
maxQueueSize,
4444
} = usePosts();
4545
46+
// Extension version from manifest
47+
const extensionVersion = computed(() => {
48+
if (typeof chrome !== 'undefined' && chrome.runtime?.getManifest) {
49+
return chrome.runtime.getManifest().version;
50+
}
51+
return '';
52+
});
53+
4654
// AI matching state (includes heat check)
4755
const isAIMatching = ref(false);
4856
const aiMatchError = ref<string | null>(null);
@@ -241,6 +249,28 @@ function handleOpenQueued(postId: string, platform: string) {
241249
}
242250
}
243251
252+
// Handle skip queued post - sends message to background to skip before AI analysis
253+
async function handleSkipQueued(postId: string, platform: string) {
254+
try {
255+
const response = (await sendMessage({
256+
type: 'SKIP_QUEUED_POST',
257+
postId,
258+
platform,
259+
} as never)) as MessageResponse;
260+
261+
if (!response.success) {
262+
throw new Error(response.error ?? 'Failed to skip post');
263+
}
264+
265+
// Reload posts to reflect the change
266+
await loadPosts();
267+
toast.success('Post skipped');
268+
} catch (error) {
269+
console.error('Failed to skip queued post:', error);
270+
toast.error('Failed to skip post');
271+
}
272+
}
273+
244274
// Handle jump to queued post - sends message to content script to scroll to the post
245275
async function handleJumpToQueuedPost(postId: string, _platform: string) {
246276
try {
@@ -343,7 +373,10 @@ async function handleJumpToPost(postId: string, _platform: string) {
343373

344374
<!-- Header -->
345375
<div class="mb-4 flex items-center justify-between">
346-
<h1 class="text-xl font-bold text-gray-900">ReplyQueue</h1>
376+
<div class="flex items-baseline gap-2">
377+
<h1 class="text-xl font-bold text-gray-900">ReplyQueue</h1>
378+
<span v-if="extensionVersion" class="text-xs text-gray-400">v{{ extensionVersion }}</span>
379+
</div>
347380
<div class="flex items-center gap-2">
348381
<TabStatusBadge :is-active="isActiveOnPlatform" :platform="currentPlatform" />
349382
<button
@@ -577,6 +610,7 @@ async function handleJumpToPost(postId: string, _platform: string) {
577610
:post="post"
578611
@open="handleOpenQueued"
579612
@jump-to-post="handleJumpToQueuedPost"
613+
@skip="handleSkipQueued"
580614
/>
581615
</div>
582616

0 commit comments

Comments
 (0)