Files
daily-notification-plugin/www/index.html
2025-11-19 05:19:24 +00:00

434 lines
20 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>DailyNotification Plugin Test</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: white;
}
.container {
max-width: 600px;
margin: 0 auto;
text-align: center;
}
h1 {
margin-bottom: 30px;
font-size: 2.5em;
}
.button {
background: rgba(255, 255, 255, 0.2);
border: 2px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 15px 30px;
margin: 10px;
border-radius: 25px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;
}
.button:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
.status {
margin-top: 30px;
padding: 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
font-family: monospace;
}
</style>
</head>
<body>
<div class="container">
<div id="statusCard" class="status" style="margin-bottom: 20px; font-size: 14px;">
<strong>Plugin Status</strong><br>
<div style="margin-top: 10px;">
⚙️ Plugin Settings: <span id="configStatus">Not configured</span><br>
🔌 Native Fetcher: <span id="fetcherStatus">Not configured</span><br>
🔔 Notifications: <span id="notificationPermStatus">Checking...</span><br>
⏰ Exact Alarms: <span id="exactAlarmPermStatus">Checking...</span><br>
📢 Channel: <span id="channelStatus">Checking...</span><br>
<div id="pluginStatusContent" style="margin-top: 8px;">
Loading plugin status...
</div>
</div>
</div>
<button class="button" onclick="configurePlugin()">Configure Plugin</button>
<button class="button" onclick="requestPermissions()">Request Permissions</button>
<button class="button" onclick="testNotification()">Test Notification</button>
<button class="button" onclick="checkComprehensiveStatus()">Full System Status</button>
<div id="status" class="status">
Ready to test...
</div>
</div>
<script>
console.log('Script loading...');
console.log('JavaScript is working!');
// Use real DailyNotification plugin
console.log('Using real DailyNotification plugin...');
window.DailyNotification = window.Capacitor.Plugins.DailyNotification;
// Define functions immediately and attach to window
function configurePlugin() {
console.log('configurePlugin called');
const status = document.getElementById('status');
const configStatus = document.getElementById('configStatus');
const fetcherStatus = document.getElementById('fetcherStatus');
status.innerHTML = 'Configuring plugin...';
status.style.background = 'rgba(255, 255, 0, 0.3)'; // Yellow background
// Update top status to show configuring
configStatus.innerHTML = '⏳ Configuring...';
fetcherStatus.innerHTML = '⏳ Waiting...';
try {
if (!window.DailyNotification) {
status.innerHTML = 'DailyNotification plugin not available';
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
configStatus.innerHTML = '❌ Plugin unavailable';
fetcherStatus.innerHTML = '❌ Plugin unavailable';
return;
}
// Configure plugin settings
window.DailyNotification.configure({
storage: 'tiered',
ttlSeconds: 86400,
prefetchLeadMinutes: 60,
maxNotificationsPerDay: 3,
retentionDays: 7
})
.then(() => {
console.log('Plugin settings configured, now configuring native fetcher...');
// Update top status
configStatus.innerHTML = '✅ Configured';
// Configure native fetcher with demo credentials
// Note: DemoNativeFetcher uses hardcoded mock data, so this is optional
// but demonstrates the API. In production, this would be real credentials.
return window.DailyNotification.configureNativeFetcher({
apiBaseUrl: 'http://10.0.2.2:3000', // Android emulator → host localhost
activeDid: 'did:ethr:0xDEMO1234567890', // Demo DID
jwtSecret: 'demo-jwt-secret-for-development-testing'
});
})
.then(() => {
// Update top status
fetcherStatus.innerHTML = '✅ Configured';
// Update bottom status for user feedback
status.innerHTML = 'Plugin configured successfully!';
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
})
.catch(error => {
// Update top status with error
if (configStatus.innerHTML.includes('Configuring')) {
configStatus.innerHTML = '❌ Failed';
}
if (fetcherStatus.innerHTML.includes('Waiting') || fetcherStatus.innerHTML.includes('Configuring')) {
fetcherStatus.innerHTML = '❌ Failed';
}
status.innerHTML = `Configuration failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
});
} catch (error) {
configStatus.innerHTML = '❌ Error';
fetcherStatus.innerHTML = '❌ Error';
status.innerHTML = `Configuration failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
}
}
function loadPluginStatus() {
console.log('loadPluginStatus called');
const pluginStatusContent = document.getElementById('pluginStatusContent');
const statusCard = document.getElementById('statusCard');
try {
if (!window.DailyNotification) {
pluginStatusContent.innerHTML = '❌ DailyNotification plugin not available';
statusCard.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
return;
}
window.DailyNotification.getNotificationStatus()
.then(result => {
const nextTime = result.nextNotificationTime ? new Date(result.nextNotificationTime).toLocaleString() : 'None scheduled';
const hasSchedules = result.isEnabled || (result.pending && result.pending > 0);
const statusIcon = hasSchedules ? '✅' : '⏸️';
pluginStatusContent.innerHTML = `${statusIcon} Active Schedules: ${hasSchedules ? 'Yes' : 'No'}<br>
📅 Next Notification: ${nextTime}<br>
⏳ Pending: ${result.pending || 0}`;
statusCard.style.background = hasSchedules ?
'rgba(0, 255, 0, 0.15)' : 'rgba(255, 255, 255, 0.1)'; // Green if active, light gray if none
})
.catch(error => {
pluginStatusContent.innerHTML = `⚠️ Status check failed: ${error.message}`;
statusCard.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
});
} catch (error) {
pluginStatusContent.innerHTML = `⚠️ Status check failed: ${error.message}`;
statusCard.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
}
}
// Notification test functions
function testNotification() {
console.log('testNotification called');
// Quick sanity check - test plugin availability
if (window.Capacitor && window.Capacitor.isPluginAvailable) {
const isAvailable = window.Capacitor.isPluginAvailable('DailyNotification');
console.log('is plugin available?', isAvailable);
}
const status = document.getElementById('status');
status.innerHTML = 'Testing plugin connection...';
status.style.background = 'rgba(255, 255, 0, 0.3)'; // Yellow background
try {
if (!window.DailyNotification) {
status.innerHTML = 'DailyNotification plugin not available';
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
return;
}
// Test the notification method directly
console.log('Testing notification scheduling...');
const now = new Date();
const notificationTime = new Date(now.getTime() + 240000); // 4 minutes from now
const prefetchTime = new Date(now.getTime() + 120000); // 2 minutes from now (2 min before notification)
const notificationTimeString = notificationTime.getHours().toString().padStart(2, '0') + ':' +
notificationTime.getMinutes().toString().padStart(2, '0');
const prefetchTimeString = prefetchTime.getHours().toString().padStart(2, '0') + ':' +
prefetchTime.getMinutes().toString().padStart(2, '0');
window.DailyNotification.scheduleDailyNotification({
time: notificationTimeString,
title: 'Test Notification',
body: 'This is a test notification from the DailyNotification plugin!',
sound: true,
priority: 'high'
})
.then(() => {
const prefetchTimeReadable = prefetchTime.toLocaleTimeString();
const notificationTimeReadable = notificationTime.toLocaleTimeString();
status.innerHTML = '✅ Notification scheduled!<br>' +
'📥 Prefetch: ' + prefetchTimeReadable + ' (' + prefetchTimeString + ')<br>' +
'🔔 Notification: ' + notificationTimeReadable + ' (' + notificationTimeString + ')';
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
// Refresh plugin status display
setTimeout(() => loadPluginStatus(), 500);
})
.catch(error => {
// Check if this is an exact alarm permission error
if (error.code === 'EXACT_ALARM_PERMISSION_REQUIRED' ||
error.message.includes('Exact alarm permission') ||
error.message.includes('Alarms & reminders')) {
status.innerHTML = '⚠️ Exact Alarm Permission Required<br><br>' +
'Settings opened automatically.<br>' +
'Please enable "Allow exact alarms" and return to try again.';
status.style.background = 'rgba(255, 165, 0, 0.3)'; // Orange background
} else {
status.innerHTML = `❌ Notification failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
}
});
} catch (error) {
status.innerHTML = `Notification test failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
}
}
// Permission management functions
function requestPermissions() {
console.log('requestPermissions called');
const status = document.getElementById('status');
status.innerHTML = 'Requesting permissions...';
status.style.background = 'rgba(255, 255, 0, 0.3)'; // Yellow background
try {
if (!window.DailyNotification) {
status.innerHTML = 'DailyNotification plugin not available';
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
return;
}
window.DailyNotification.requestNotificationPermissions()
.then(() => {
status.innerHTML = 'Permission request completed! Check your device settings if needed.';
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
// Refresh permission and channel status display after request
setTimeout(() => {
loadPermissionStatus();
loadChannelStatus();
}, 1000);
})
.catch(error => {
status.innerHTML = `Permission request failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
});
} catch (error) {
status.innerHTML = `Permission request failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
}
}
function loadChannelStatus() {
const channelStatus = document.getElementById('channelStatus');
try {
if (!window.DailyNotification) {
channelStatus.innerHTML = '❌ Plugin unavailable';
return;
}
window.DailyNotification.isChannelEnabled()
.then(result => {
const importanceText = getImportanceText(result.importance);
if (result.enabled) {
channelStatus.innerHTML = `✅ Enabled (${importanceText})`;
} else {
channelStatus.innerHTML = `❌ Disabled (${importanceText})`;
}
})
.catch(error => {
channelStatus.innerHTML = '⚠️ Error';
});
} catch (error) {
channelStatus.innerHTML = '⚠️ Error';
}
}
function checkComprehensiveStatus() {
const status = document.getElementById('status');
status.innerHTML = 'Checking comprehensive status...';
status.style.background = 'rgba(255, 255, 0, 0.3)'; // Yellow background
try {
if (!window.DailyNotification) {
status.innerHTML = 'DailyNotification plugin not available';
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
return;
}
window.DailyNotification.checkStatus()
.then(result => {
const canSchedule = result.canScheduleNow;
const issues = [];
if (!result.postNotificationsGranted) {
issues.push('POST_NOTIFICATIONS permission');
}
if (!result.channelEnabled) {
issues.push('notification channel disabled');
}
if (!result.exactAlarmsGranted) {
issues.push('exact alarm permission');
}
let statusText = `Status: ${canSchedule ? 'Ready to schedule' : 'Issues found'}`;
if (issues.length > 0) {
statusText += `\nIssues: ${issues.join(', ')}`;
}
statusText += `\nChannel: ${getImportanceText(result.channelImportance)}`;
statusText += `\nChannel ID: ${result.channelId}`;
status.innerHTML = statusText;
status.style.background = canSchedule ? 'rgba(0, 255, 0, 0.3)' : 'rgba(255, 0, 0, 0.3)';
})
.catch(error => {
status.innerHTML = `Status check failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
});
} catch (error) {
status.innerHTML = `Status check failed: ${error.message}`;
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
}
}
function getImportanceText(importance) {
switch (importance) {
case 0: return 'None (blocked)';
case 1: return 'Min';
case 2: return 'Low';
case 3: return 'Default';
case 4: return 'High';
case 5: return 'Max';
default: return `Unknown (${importance})`;
}
}
// Attach to window object
window.configurePlugin = configurePlugin;
window.testNotification = testNotification;
window.requestPermissions = requestPermissions;
window.checkComprehensiveStatus = checkComprehensiveStatus;
function loadPermissionStatus() {
const notificationPermStatus = document.getElementById('notificationPermStatus');
const exactAlarmPermStatus = document.getElementById('exactAlarmPermStatus');
try {
if (!window.DailyNotification) {
notificationPermStatus.innerHTML = '❌ Plugin unavailable';
exactAlarmPermStatus.innerHTML = '❌ Plugin unavailable';
return;
}
window.DailyNotification.checkPermissionStatus()
.then(result => {
notificationPermStatus.innerHTML = result.notificationsEnabled ? '✅ Granted' : '❌ Not granted';
exactAlarmPermStatus.innerHTML = result.exactAlarmEnabled ? '✅ Granted' : '❌ Not granted';
})
.catch(error => {
notificationPermStatus.innerHTML = '⚠️ Error';
exactAlarmPermStatus.innerHTML = '⚠️ Error';
});
} catch (error) {
notificationPermStatus.innerHTML = '⚠️ Error';
exactAlarmPermStatus.innerHTML = '⚠️ Error';
}
}
// Load plugin status automatically on page load
window.addEventListener('load', () => {
console.log('Page loaded, loading plugin status...');
// Small delay to ensure Capacitor is ready
setTimeout(() => {
loadPluginStatus();
loadPermissionStatus();
loadChannelStatus();
}, 500);
});
console.log('Functions attached to window:', {
configurePlugin: typeof window.configurePlugin,
testNotification: typeof window.testNotification
});
</script>
</body>
</html>