Skip to content

Commit 74e9dbe

Browse files
committed
feat: Add manual refresh button for prompts and enhance loading states in mobile PWA
1 parent 120078d commit 74e9dbe

File tree

8 files changed

+118
-46
lines changed

8 files changed

+118
-46
lines changed

CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,24 @@ All notable changes to Promptzy will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [1.3.1]
9+
10+
### Added
11+
- **🔄 Refresh Prompts Button:** Added manual refresh button in header for both web and mobile PWA
12+
- **📱 Mobile PWA Sync:** Refresh button specifically addresses mobile PWA prompt loading after Supabase configuration
13+
- **🔄 Smart Connection Check:** Refresh function re-validates Supabase connection before loading prompts
14+
- **✨ Loading States:** Visual feedback with spinning icon and disabled button during refresh operation
15+
- **📢 User Feedback:** Toast notifications for refresh success, failure, and connection issues
16+
17+
### Changed
18+
- **🎨 Header Layout:** Refresh button positioned between logo and settings for easy access
19+
- **📱 Responsive Design:** Refresh button adapts to mobile with proper touch targets and responsive text
20+
- **⚡ Performance:** Extracted prompt loading logic into reusable function for better code organization
21+
22+
### Fixed
23+
- **📱 Mobile PWA Issue:** Prompts now properly load after entering Supabase credentials on mobile app
24+
- **🔄 Cross-Device Sync:** Manual refresh ensures prompts appear when switching devices or browsers
25+
- **🔗 Connection Reliability:** Refresh validates connection before attempting to load data
926

1027
## [1.3.0] - 2025-05-28
1128

OVERVIEW.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ✨ Promptzy 🎯
22

3-
**Last Updated:** 2025-05-28T01:47:10.617Z
3+
**Last Updated:** 2025-05-29T03:05:39.954Z
44

55
## Project Overview
66

@@ -12,6 +12,7 @@
1212
- **Prompt Types:** Support for system, task, image, and video prompts with type-specific badges
1313
- **Tagging System:** Organize prompts with customizable tags and visual tag chips
1414
- **Search & Filter:** Full-text search and tag-based filtering with responsive masonry layout
15+
- **Manual Refresh:** Dedicated refresh button in header for syncing prompts after configuration changes
1516
- **AI Assistant:** Generate new prompt ideas using Pollinations.ai API with streaming responses and collapsible interface
1617
- **Cloud Storage:**
1718
- Supabase-only storage for reliable cloud persistence
@@ -29,6 +30,7 @@
2930
- Service worker for offline functionality and caching
3031
- Native app experience with no browser UI
3132
- Auto-updates and home screen installation
33+
- Manual refresh button for mobile PWA sync after Supabase setup
3234
- **Settings & Configuration:** Comprehensive settings dialog with Supabase connection testing and system prompt management
3335
- **Theming & Responsive Design:** Custom purple theme with dark/light mode support and smooth animations
3436
- **Global Installation:** npm global installation support with CLI commands (`promptzy`, `prompt-dashboard`, `ai-prompt-dashboard`)
@@ -80,7 +82,7 @@ promptzy/
8082
│ │ ├── SearchInput.tsx # Search input with icon
8183
│ │ ├── TagFilter.tsx # Tag filtering buttons
8284
│ │ ├── EmptyState.tsx # Contextual empty states
83-
│ │ ├── Header.tsx # App header with settings
85+
│ │ ├── Header.tsx # App header with refresh, settings, and add buttons
8486
│ │ ├── SettingsDialog.tsx # Comprehensive settings modal
8587
│ │ └── ui/ # Shadcn UI & Radix primitives (40+ components)
8688
│ ├── hooks/ # Custom React hooks (use-toast, use-mobile)
@@ -140,14 +142,15 @@ For detailed deployment instructions, see the [DEPLOYMENT.md](DEPLOYMENT.md) gui
140142

141143
- **✅ Storage Simplified:** Removed localStorage and sync functionality - now uses Supabase-only storage for reliability
142144
- **✅ Sync Issues Resolved:** Eliminated prompt duplication and cross-browser sync problems by removing hybrid storage
145+
- **✅ Manual Refresh Button:** Added refresh button in header to solve mobile PWA sync issues after Supabase configuration
143146
- **✅ Global CLI Support:** Added npm global installation with `promptzy`, `prompt-dashboard` and `ai-prompt-dashboard` commands
144147
- **✅ Progressive Web App:** Added PWA functionality for mobile app installation directly from browser
145148
- **✅ Mobile Responsive:** Fixed mobile layout issues with header, buttons, and AI assistant panel
146149
- **✅ Clean Settings:** Removed default Supabase credentials - settings form now starts blank
147150
- **Authentication:** User prefers login-based authentication system with multiple options (Google, GitHub, email/password) over anonymous user IDs
148151
- **✅ Cloud Operations:** All CRUD operations now properly update Supabase database with proper error handling
149152
- **✅ Rebranded to Promptzy:** Updated from "AI Prompt Dashboard" to "Promptzy" with cute new branding and logo
150-
- **✅ Version Updated:** Current version 1.3.0 with PWA functionality and mobile optimization
153+
- **✅ Version Updated:** Current version 1.3.0+ with PWA functionality, mobile optimization, and refresh functionality
151154

152155
## 🔮 Future Enhancements
153156

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<div align="center">
1010

1111
![License](https://img.shields.io/badge/license-MIT-blue.svg)
12-
![Version](https://img.shields.io/badge/version-1.2.0-green.svg)
12+
![Version](https://img.shields.io/badge/version-1.3.1-green.svg)
1313
![NPM](https://img.shields.io/npm/v/@pinkpixel/promptzy?color=red)
1414
![React](https://img.shields.io/badge/React-19.1.0-61DAFB?logo=react)
1515
![TypeScript](https://img.shields.io/badge/TypeScript-5.8.3-3178C6?logo=typescript)
@@ -27,10 +27,8 @@
2727
- **Organize AI Prompts**: Store, edit, and categorize prompts for various AI models
2828
- **Custom Tagging**: Organize prompts with custom tags for easy retrieval
2929
- **Powerful Search**: Find the perfect prompt with full-text search and tag filtering
30-
- **Dual Storage**:
31-
- Store prompts locally in your browser
32-
- Cloud sync with Supabase for cross-device access
33-
- Optional hybrid mode to sync between both
30+
- **Cloud Storage**: Reliable Supabase cloud storage with cross-device sync
31+
- **Refresh Prompts**: Manual refresh button to sync prompts after configuration changes
3432
- **AI Assistant**: Generate new prompt ideas with AI help
3533
- **Progressive Web App (PWA)**: Install as a mobile app directly from your browser
3634
- **Modern UI**: Clean, responsive interface built with Shadcn/UI and Tailwind
@@ -109,6 +107,7 @@ Promptzy can be installed as a mobile app directly from your browser! No app sto
109107
- ⚡ Faster loading and offline functionality
110108
- 🔄 Automatic updates when new versions are released
111109
- 🏠 Easy access from your home screen
110+
- 🔄 Manual refresh button for syncing prompts after setup
112111

113112
### Deployment
114113

@@ -141,8 +140,9 @@ To use cloud storage features:
141140
- Paste and run it in the Supabase SQL Editor
142141
4. Return to Promptzy and click "Connect" again to verify the table setup
143142
5. Save your settings
143+
6. Use the "Refresh" button in the header to load your prompts
144144

145-
**Note:** Automatic table creation isn't supported by Supabase for security reasons, so this one-time manual setup is required.
145+
**Note:** Automatic table creation isn't supported by Supabase for security reasons, so this one-time manual setup is required. After setup, use the refresh button to ensure prompts load properly, especially on mobile devices.
146146

147147
The application will now use your Supabase instance for cloud storage!
148148

@@ -165,11 +165,12 @@ This bidirectional sync ensures your prompts are available across devices and yo
165165
## 📖 Usage
166166

167167
1. Launch the application
168-
2. Choose your storage preference (local, Supabase, or both)
169-
3. Add prompts with the "+" button
170-
4. Assign tags to organize your prompts
171-
5. Use the search box and tag filters to find prompts
172-
6. Select a prompt to copy it or edit its details
168+
2. Configure your Supabase connection in Settings
169+
3. Use the "Refresh" button to load your prompts after setup
170+
4. Add prompts with the "+" button
171+
5. Assign tags to organize your prompts
172+
6. Use the search box and tag filters to find prompts
173+
7. Select a prompt to copy it or edit its details
173174

174175
## 🧩 Tech Stack
175176

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pinkpixel/promptzy",
3-
"version": "1.3.0",
3+
"version": "1.3.1",
44
"description": "Promptzy - A modern, cute web application for managing and organizing your AI prompts, with tagging, search, and cloud storage.",
55
"type": "module",
66
"main": "dist/index.html",

src/components/Header.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import React, { useState } from "react";
22
import { Button } from "@/components/ui/button";
3-
import { Plus, Settings } from "lucide-react";
3+
import { Plus, Settings, RefreshCw } from "lucide-react";
44
import SettingsDialog from "@/components/SettingsDialog";
55

66
interface HeaderProps {
77
onAddPrompt: () => void;
8+
onRefreshPrompts: () => void;
9+
isRefreshing: boolean;
810
}
911

10-
const Header: React.FC<HeaderProps> = ({ onAddPrompt }) => {
12+
const Header: React.FC<HeaderProps> = ({ onAddPrompt, onRefreshPrompts, isRefreshing }) => {
1113
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
1214

1315
return (
@@ -17,6 +19,16 @@ const Header: React.FC<HeaderProps> = ({ onAddPrompt }) => {
1719
<h1 className="text-2xl sm:text-3xl font-bold">Promptzy</h1>
1820
</div>
1921
<div className="flex gap-2 w-full sm:w-auto">
22+
<Button
23+
variant="outline"
24+
size="sm"
25+
onClick={onRefreshPrompts}
26+
disabled={isRefreshing}
27+
className="flex items-center gap-1 flex-1 sm:flex-none"
28+
>
29+
<RefreshCw className={`h-4 w-4 ${isRefreshing ? 'animate-spin' : ''}`} />
30+
<span className="hidden xs:inline">{isRefreshing ? 'Refreshing...' : 'Refresh'}</span>
31+
</Button>
2032
<Button
2133
variant="outline"
2234
size="sm"

src/lib/supabasePromptStore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const getUserId = async (client: ReturnType<typeof createClient>): Promise<strin
114114
}
115115

116116
// If no authenticated user, check for a custom user ID set by the user
117-
let customUserId = localStorage.getItem('custom-user-id');
117+
const customUserId = localStorage.getItem('custom-user-id');
118118
if (customUserId && customUserId.trim()) {
119119
console.log("Using custom user ID:", customUserId);
120120
return customUserId.trim();

src/pages/Index.tsx

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const Index = () => {
3535
const [editingPrompt, setEditingPrompt] = useState<Prompt | null>(null);
3636
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
3737
const [supabaseConnected, setSupabaseConnected] = useState<boolean>(false);
38+
const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
3839
const { toast } = useToast();
3940

4041
// Delete confirmation state
@@ -92,40 +93,76 @@ const Index = () => {
9293
};
9394
}, [checkSupabaseConnection]);
9495

95-
// Load prompts from Supabase
96+
// Function to load prompts from Supabase (extracted for reuse)
97+
const loadPrompts = useCallback(async () => {
98+
console.log("Loading prompts from Supabase, connected:", supabaseConnected);
99+
100+
if (!supabaseConnected) {
101+
console.log("Supabase not connected, skipping prompt load");
102+
return;
103+
}
104+
105+
try {
106+
const supabasePrompts = await getPromptsFromSupabase();
107+
console.log(`Retrieved ${supabasePrompts.length} prompts from Supabase`);
108+
109+
setPrompts(supabasePrompts);
110+
// Extract unique tags from prompts
111+
const tagsFromSupabase = supabasePrompts.flatMap(p => p.tags);
112+
const uniqueTags = Array.from(
113+
new Map(tagsFromSupabase.map(tag => [tag.id, tag])).values()
114+
);
115+
setAllTags(uniqueTags);
116+
} catch (error) {
117+
console.error("Error loading prompts from Supabase:", error);
118+
toast({
119+
title: "Error loading prompts",
120+
description: "Could not load prompts from Supabase. Please check your connection.",
121+
variant: "destructive",
122+
});
123+
}
124+
}, [supabaseConnected, toast]);
125+
126+
// Load prompts from Supabase on mount and connection changes
96127
useEffect(() => {
97-
const loadPrompts = async () => {
98-
console.log("Loading prompts from Supabase, connected:", supabaseConnected);
128+
loadPrompts();
129+
}, [loadPrompts]);
99130

100-
if (!supabaseConnected) {
101-
console.log("Supabase not connected, skipping prompt load");
102-
return;
103-
}
131+
// Function to handle manual refresh
132+
const handleRefreshPrompts = useCallback(async () => {
133+
setIsRefreshing(true);
134+
135+
try {
136+
// Re-check Supabase connection first
137+
const isConnected = await checkSupabaseConnection();
104138

105-
try {
106-
const supabasePrompts = await getPromptsFromSupabase();
107-
console.log(`Retrieved ${supabasePrompts.length} prompts from Supabase`);
108-
109-
setPrompts(supabasePrompts);
110-
// Extract unique tags from prompts
111-
const tagsFromSupabase = supabasePrompts.flatMap(p => p.tags);
112-
const uniqueTags = Array.from(
113-
new Map(tagsFromSupabase.map(tag => [tag.id, tag])).values()
114-
);
115-
setAllTags(uniqueTags);
116-
} catch (error) {
117-
console.error("Error loading prompts from Supabase:", error);
139+
if (!isConnected) {
118140
toast({
119-
title: "Error loading prompts",
120-
description: "Could not load prompts from Supabase. Please check your connection.",
141+
title: "Connection Failed",
142+
description: "Could not connect to Supabase. Please check your settings.",
121143
variant: "destructive",
122144
});
145+
return;
123146
}
124-
};
125147

126-
loadPrompts();
127-
}, [supabaseConnected, toast, checkSupabaseConnection]);
148+
// Load prompts if connected
149+
await loadPrompts();
128150

151+
toast({
152+
title: "Prompts Refreshed",
153+
description: "Successfully refreshed prompts from Supabase.",
154+
});
155+
} catch (error) {
156+
console.error("Error refreshing prompts:", error);
157+
toast({
158+
title: "Refresh Failed",
159+
description: "Could not refresh prompts. Please try again.",
160+
variant: "destructive",
161+
});
162+
} finally {
163+
setIsRefreshing(false);
164+
}
165+
}, [checkSupabaseConnection, loadPrompts, toast]);
129166

130167
const handleAddPrompt = () => {
131168
setEditingPrompt(null);
@@ -305,6 +342,8 @@ const Index = () => {
305342
<div className="container mx-auto py-8 px-4 min-h-screen max-w-5xl">
306343
<Header
307344
onAddPrompt={handleAddPrompt}
345+
onRefreshPrompts={handleRefreshPrompts}
346+
isRefreshing={isRefreshing}
308347
/>
309348

310349
<div className="mb-8 space-y-6">

0 commit comments

Comments
 (0)