@djangocfg/layouts 2.1.37 → 2.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +204 -18
- package/package.json +5 -5
- package/src/components/errors/index.ts +9 -0
- package/src/components/errors/types.ts +38 -0
- package/src/layouts/AppLayout/AppLayout.tsx +33 -45
- package/src/layouts/AppLayout/BaseApp.tsx +104 -33
- package/src/layouts/AuthLayout/AuthContext.tsx +7 -1
- package/src/layouts/AuthLayout/OAuthProviders.tsx +1 -10
- package/src/layouts/AuthLayout/OTPForm.tsx +1 -0
- package/src/layouts/PrivateLayout/PrivateLayout.tsx +1 -1
- package/src/layouts/PublicLayout/PublicLayout.tsx +1 -1
- package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +1 -1
- package/src/layouts/PublicLayout/components/PublicNavigation.tsx +1 -1
- package/src/layouts/_components/UserMenu.tsx +1 -1
- package/src/layouts/index.ts +1 -1
- package/src/layouts/types/index.ts +47 -0
- package/src/layouts/types/layout.types.ts +61 -0
- package/src/layouts/types/providers.types.ts +65 -0
- package/src/layouts/types/ui.types.ts +103 -0
- package/src/snippets/Analytics/index.ts +1 -0
- package/src/snippets/Analytics/types.ts +10 -0
- package/src/snippets/PWAInstall/@docs/README.md +92 -0
- package/src/snippets/PWAInstall/README.md +185 -0
- package/src/snippets/{PWA → PWAInstall}/components/A2HSHint.tsx +85 -84
- package/src/snippets/PWAInstall/components/DesktopGuide.tsx +229 -0
- package/src/snippets/PWAInstall/context/InstallContext.tsx +102 -0
- package/src/snippets/{PWA → PWAInstall}/hooks/useInstallPrompt.ts +3 -0
- package/src/snippets/{PWA → PWAInstall}/index.ts +12 -31
- package/src/snippets/{PWA → PWAInstall}/types/components.ts +0 -6
- package/src/snippets/PWAInstall/types/config.ts +22 -0
- package/src/snippets/{PWA → PWAInstall}/types/index.ts +4 -4
- package/src/snippets/{PWA → PWAInstall}/utils/localStorage.ts +1 -23
- package/src/snippets/PushNotifications/@docs/README.md +191 -0
- package/src/snippets/PushNotifications/@docs/guides/django-integration.md +648 -0
- package/src/snippets/PushNotifications/@docs/guides/service-worker.md +467 -0
- package/src/snippets/PushNotifications/@docs/guides/vapid-setup.md +352 -0
- package/src/snippets/PushNotifications/README.md +328 -0
- package/src/snippets/{PWA → PushNotifications}/config.ts +2 -2
- package/src/snippets/PushNotifications/context/DjangoPushContext.tsx +190 -0
- package/src/snippets/{PWA → PushNotifications}/hooks/useDjangoPush.ts +63 -81
- package/src/snippets/{PWA → PushNotifications}/hooks/usePushNotifications.ts +12 -8
- package/src/snippets/PushNotifications/index.ts +87 -0
- package/src/snippets/PushNotifications/types/config.ts +28 -0
- package/src/snippets/PushNotifications/types/index.ts +9 -0
- package/src/snippets/PushNotifications/utils/localStorage.ts +60 -0
- package/src/snippets/PushNotifications/utils/logger.ts +149 -0
- package/src/snippets/PushNotifications/utils/platform.ts +151 -0
- package/src/snippets/index.ts +37 -12
- package/src/layouts/shared/index.ts +0 -21
- package/src/layouts/shared/types.ts +0 -247
- package/src/snippets/PWA/@refactoring/ARCHITECTURE_ANALYSIS.md +0 -1179
- package/src/snippets/PWA/@refactoring/EXECUTIVE_SUMMARY.md +0 -271
- package/src/snippets/PWA/@refactoring/README.md +0 -204
- package/src/snippets/PWA/@refactoring/REFACTORING_PROPOSALS.md +0 -1109
- package/src/snippets/PWA/@refactoring2/COMPARISON-WITH-NEXTJS.md +0 -718
- package/src/snippets/PWA/@refactoring2/P1-FIXES-COMPLETED.md +0 -188
- package/src/snippets/PWA/@refactoring2/POST-P0-ANALYSIS.md +0 -362
- package/src/snippets/PWA/@refactoring2/README.md +0 -85
- package/src/snippets/PWA/@refactoring2/RECOMMENDATIONS.md +0 -1321
- package/src/snippets/PWA/@refactoring2/REMAINING-ISSUES.md +0 -557
- package/src/snippets/PWA/README.md +0 -387
- package/src/snippets/PWA/context/DjangoPushContext.tsx +0 -105
- package/src/snippets/PWA/context/InstallContext.tsx +0 -118
- package/src/snippets/PWA/context/PushContext.tsx +0 -156
- /package/src/layouts/{shared → types}/README.md +0 -0
- /package/src/snippets/{PWA/@docs/research.md → PWAInstall/@docs/research/ios-android-install-flows.md} +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuide.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuideDrawer.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuideModal.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/hooks/useIsPWA.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/types/install.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/types/platform.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/utils/logger.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/utils/platform.ts +0 -0
- /package/src/snippets/{PWA → PushNotifications}/components/PushPrompt.tsx +0 -0
- /package/src/snippets/{PWA → PushNotifications}/types/push.ts +0 -0
- /package/src/snippets/{PWA → PushNotifications}/utils/vapid.ts +0 -0
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
|
4
|
-
import { usePushNotifications } from '../hooks/usePushNotifications';
|
|
5
|
-
import { pwaLogger } from '../utils/logger';
|
|
6
|
-
import type { PushNotificationOptions } from '../types';
|
|
7
|
-
|
|
8
|
-
const ICON_URL = 'https://djangocfg.com/static/logos/192x192.png';
|
|
9
|
-
|
|
10
|
-
export interface PushMessage {
|
|
11
|
-
id: string;
|
|
12
|
-
title: string;
|
|
13
|
-
body: string;
|
|
14
|
-
icon?: string;
|
|
15
|
-
badge?: string;
|
|
16
|
-
tag?: string;
|
|
17
|
-
timestamp: number;
|
|
18
|
-
data?: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface PushContextValue {
|
|
22
|
-
// Push state
|
|
23
|
-
isSupported: boolean;
|
|
24
|
-
permission: NotificationPermission;
|
|
25
|
-
isSubscribed: boolean;
|
|
26
|
-
subscription: PushSubscription | null;
|
|
27
|
-
|
|
28
|
-
// Accumulated pushes
|
|
29
|
-
pushes: PushMessage[];
|
|
30
|
-
|
|
31
|
-
// Actions
|
|
32
|
-
subscribe: () => Promise<boolean>;
|
|
33
|
-
unsubscribe: () => Promise<boolean>;
|
|
34
|
-
sendPush: (message: Omit<PushMessage, 'id' | 'timestamp'>) => Promise<void>;
|
|
35
|
-
clearPushes: () => void;
|
|
36
|
-
removePush: (id: string) => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const PushContext = createContext<PushContextValue | undefined>(undefined);
|
|
40
|
-
|
|
41
|
-
interface PushProviderProps {
|
|
42
|
-
children: React.ReactNode;
|
|
43
|
-
vapidPublicKey?: string;
|
|
44
|
-
subscribeEndpoint?: string;
|
|
45
|
-
sendEndpoint?: string;
|
|
46
|
-
onPushReceived?: (push: PushMessage) => void;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function PushProvider({
|
|
50
|
-
children,
|
|
51
|
-
vapidPublicKey = '',
|
|
52
|
-
subscribeEndpoint = '/api/push/subscribe',
|
|
53
|
-
sendEndpoint = '/api/push/send',
|
|
54
|
-
onPushReceived,
|
|
55
|
-
}: PushProviderProps) {
|
|
56
|
-
const pushNotifications = usePushNotifications({
|
|
57
|
-
vapidPublicKey,
|
|
58
|
-
subscribeEndpoint,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const [pushes, setPushes] = useState<PushMessage[]>([]);
|
|
62
|
-
|
|
63
|
-
// Listen for push messages from service worker
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
if (typeof window === 'undefined' || !('serviceWorker' in navigator)) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const handleMessage = (event: MessageEvent) => {
|
|
70
|
-
if (event.data && event.data.type === 'PUSH_RECEIVED') {
|
|
71
|
-
const push: PushMessage = {
|
|
72
|
-
id: crypto.randomUUID(),
|
|
73
|
-
timestamp: Date.now(),
|
|
74
|
-
...event.data.notification,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
setPushes(prev => [push, ...prev]);
|
|
78
|
-
onPushReceived?.(push);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
navigator.serviceWorker.addEventListener('message', handleMessage);
|
|
83
|
-
|
|
84
|
-
return () => {
|
|
85
|
-
navigator.serviceWorker.removeEventListener('message', handleMessage);
|
|
86
|
-
};
|
|
87
|
-
}, [onPushReceived]);
|
|
88
|
-
|
|
89
|
-
const sendPush = useCallback(async (message: Omit<PushMessage, 'id' | 'timestamp'>) => {
|
|
90
|
-
if (!pushNotifications.isSubscribed) {
|
|
91
|
-
throw new Error('Not subscribed to push notifications');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// In real app, this calls your backend API to send actual push
|
|
95
|
-
try {
|
|
96
|
-
// Send to server
|
|
97
|
-
await fetch(sendEndpoint, {
|
|
98
|
-
method: 'POST',
|
|
99
|
-
headers: { 'Content-Type': 'application/json' },
|
|
100
|
-
body: JSON.stringify({
|
|
101
|
-
subscription: pushNotifications.subscription,
|
|
102
|
-
notification: message,
|
|
103
|
-
}),
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// Optimistic update for UI
|
|
107
|
-
const push: PushMessage = {
|
|
108
|
-
...message,
|
|
109
|
-
id: crypto.randomUUID(),
|
|
110
|
-
timestamp: Date.now(),
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
setPushes(prev => [push, ...prev]);
|
|
114
|
-
} catch (error) {
|
|
115
|
-
pwaLogger.error('[PushContext] Failed to send push:', error);
|
|
116
|
-
throw error;
|
|
117
|
-
}
|
|
118
|
-
}, [pushNotifications.isSubscribed, pushNotifications.subscription, sendEndpoint]);
|
|
119
|
-
|
|
120
|
-
const clearPushes = useCallback(() => {
|
|
121
|
-
setPushes([]);
|
|
122
|
-
}, []);
|
|
123
|
-
|
|
124
|
-
const removePush = useCallback((id: string) => {
|
|
125
|
-
setPushes(prev => prev.filter(p => p.id !== id));
|
|
126
|
-
}, []);
|
|
127
|
-
|
|
128
|
-
const value: PushContextValue = {
|
|
129
|
-
isSupported: pushNotifications.isSupported,
|
|
130
|
-
permission: pushNotifications.permission,
|
|
131
|
-
isSubscribed: pushNotifications.isSubscribed,
|
|
132
|
-
subscription: pushNotifications.subscription,
|
|
133
|
-
pushes,
|
|
134
|
-
subscribe: pushNotifications.subscribe,
|
|
135
|
-
unsubscribe: pushNotifications.unsubscribe,
|
|
136
|
-
sendPush,
|
|
137
|
-
clearPushes,
|
|
138
|
-
removePush,
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
return <PushContext.Provider value={value}>{children}</PushContext.Provider>;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Use push notifications context
|
|
146
|
-
* Must be used within <PushProvider>
|
|
147
|
-
*/
|
|
148
|
-
export function usePush(): PushContextValue {
|
|
149
|
-
const context = useContext(PushContext);
|
|
150
|
-
|
|
151
|
-
if (context === undefined) {
|
|
152
|
-
throw new Error('usePush must be used within <PushProvider>');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return context;
|
|
156
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|