Compare commits
2 Commits
2603ca8e5c
...
e460dbd34e
| Author | SHA1 | Date | |
|---|---|---|---|
| e460dbd34e | |||
| 0de2fd942f |
@@ -170,22 +170,30 @@ type PushStatus = {
|
||||
registered: boolean;
|
||||
distributor: string;
|
||||
endpoint: string;
|
||||
distributors: string[];
|
||||
};
|
||||
|
||||
/** Android-only section showing UnifiedPush registration status and controls. */
|
||||
function AndroidPushNotifications() {
|
||||
const [status, setStatus] = useState<PushStatus | undefined>(undefined);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lastError, setLastError] = useState<string | undefined>(undefined);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
setLoading(true);
|
||||
const s = await getBackgroundSyncStatus();
|
||||
const distributors = Array.isArray(s?.distributors)
|
||||
? s.distributors
|
||||
: typeof s?.distributors === 'string' && s.distributors && s.distributors !== '[]'
|
||||
? [s.distributors]
|
||||
: [];
|
||||
setStatus(
|
||||
s
|
||||
? {
|
||||
registered: s.registered,
|
||||
distributor: s.distributor || '',
|
||||
endpoint: s.endpoint || '',
|
||||
distributors,
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
@@ -198,8 +206,14 @@ function AndroidPushNotifications() {
|
||||
|
||||
const [resetState, reset] = useAsyncCallback(
|
||||
useCallback(async () => {
|
||||
await requestResetPushRegistration();
|
||||
setLastError(undefined);
|
||||
const result = await requestResetPushRegistration();
|
||||
await refresh();
|
||||
if (!result.success) {
|
||||
setLastError(
|
||||
'Could not register a push distributor. Install ntfy (with UnifiedPush enabled), then try Reset again.'
|
||||
);
|
||||
}
|
||||
}, [refresh])
|
||||
);
|
||||
|
||||
@@ -214,6 +228,36 @@ function AndroidPushNotifications() {
|
||||
resetState.status === AsyncStatus.Loading ||
|
||||
pingState.status === AsyncStatus.Loading;
|
||||
|
||||
const statusDescription = (() => {
|
||||
if (loading) return 'Loading status…';
|
||||
if (status === undefined) {
|
||||
return (
|
||||
<Text as="span" style={{ color: color.Critical.Main }} size="T200">
|
||||
Failed to read push status.
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
if (status.registered) {
|
||||
return (
|
||||
<Text as="span" size="T200">
|
||||
{`Distributor: ${status.distributor || 'unknown'}`}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
if (status.distributors.length === 0) {
|
||||
return (
|
||||
<Text as="span" style={{ color: color.Critical.Main }} size="T200">
|
||||
No UnifiedPush distributor found. Install ntfy from Play Store/F-Droid and enable UnifiedPush in ntfy settings.
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Text as="span" style={{ color: color.Warning?.Main ?? color.Critical.Main }} size="T200">
|
||||
{`Found ${status.distributors.join(', ')} but not registered yet. Tap Reset and pick ntfy.`}
|
||||
</Text>
|
||||
);
|
||||
})();
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Android Push (UnifiedPush)</Text>
|
||||
@@ -226,29 +270,20 @@ function AndroidPushNotifications() {
|
||||
<SettingTile
|
||||
title="Background Notifications"
|
||||
description={
|
||||
loading ? (
|
||||
'Loading status…'
|
||||
) : status === undefined ? (
|
||||
<Text as="span" style={{ color: color.Critical.Main }} size="T200">
|
||||
Failed to read push status.
|
||||
</Text>
|
||||
) : status.registered ? (
|
||||
<>
|
||||
<Text as="span" size="T200">
|
||||
{`Distributor: ${status.distributor || 'unknown'}`}
|
||||
<>
|
||||
{statusDescription}
|
||||
{lastError ? (
|
||||
<Text as="span" style={{ color: color.Critical.Main, display: 'block' }} size="T200">
|
||||
{lastError}
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<Text as="span" style={{ color: color.Warning?.Main ?? color.Critical.Main }} size="T200">
|
||||
Not registered. Tap "Reset" to choose a distributor app.
|
||||
</Text>
|
||||
)
|
||||
) : null}
|
||||
</>
|
||||
}
|
||||
after={loading ? <Spinner variant="Secondary" /> : undefined}
|
||||
/>
|
||||
<SettingTile
|
||||
title="Change Distributor"
|
||||
description="Re-open the UnifiedPush distributor selection dialog."
|
||||
description="Shows a list of installed UnifiedPush apps (ntfy, etc.) and registers the one you pick."
|
||||
after={
|
||||
<Button
|
||||
size="300"
|
||||
|
||||
@@ -55,6 +55,8 @@ interface MatrixBackgroundSyncPlugin {
|
||||
setAppForeground(options: { foreground: boolean }): Promise<void>;
|
||||
/** Returns fetch state and current UnifiedPush registration details. */
|
||||
getStatus(): Promise<UnifiedPushStatus>;
|
||||
/** Native Matrix gateway discovery for a UnifiedPush endpoint (avoids WebView CORS). */
|
||||
resolveUnifiedPushGateway(options: { endpoint: string }): Promise<{ gatewayUrl: string }>;
|
||||
addListener(
|
||||
eventName: 'unifiedPushNewEndpoint',
|
||||
listenerFunc: (event: UnifiedPushEndpointEvent) => void
|
||||
@@ -141,6 +143,17 @@ const normalizeDistributors = (raw: UnifiedPushStatus['distributors']): string[]
|
||||
};
|
||||
|
||||
const resolveUnifiedPushGateway = async (endpoint: string): Promise<string> => {
|
||||
// Prefer native HTTP — ntfy/Matrix gateway responses omit CORS headers, so
|
||||
// WebView fetch fails with TypeError: Failed to fetch and wrongly falls back.
|
||||
try {
|
||||
const { registerPlugin } = await loadCapacitorCore();
|
||||
const MatrixBackgroundSync = registerPlugin<MatrixBackgroundSyncPlugin>('MatrixBackgroundSync');
|
||||
const result = await MatrixBackgroundSync.resolveUnifiedPushGateway({ endpoint });
|
||||
if (result?.gatewayUrl) return result.gatewayUrl;
|
||||
} catch (err) {
|
||||
console.warn('[BackgroundSync] Native UnifiedPush gateway discovery failed:', err);
|
||||
}
|
||||
|
||||
try {
|
||||
const discoveryUrl = new URL(endpoint);
|
||||
discoveryUrl.pathname = '/_matrix/push/v1/notify';
|
||||
@@ -529,7 +542,18 @@ export const requestResetPushRegistration = async (): Promise<{ success: boolean
|
||||
const MatrixBackgroundSync = registerPlugin<MatrixBackgroundSyncPlugin>('MatrixBackgroundSync');
|
||||
const result = await MatrixBackgroundSync.requestDistributorSetup();
|
||||
console.log('[BackgroundSync] requestDistributorSetup completed:', result);
|
||||
return result ?? { success: false };
|
||||
if (!result?.success) return { success: false };
|
||||
|
||||
// Endpoint arrives asynchronously from the distributor after register().
|
||||
for (let i = 0; i < 20; i += 1) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
const status = await getBackgroundSyncStatus();
|
||||
if (status?.registered && status.endpoint) {
|
||||
return { success: true };
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
console.error('[BackgroundSync] requestDistributorSetup failed:', err);
|
||||
return { success: false };
|
||||
|
||||
Reference in New Issue
Block a user