feat(ios): implement Phase 1 permission methods and fix build issues
Implement checkPermissionStatus() and requestNotificationPermissions() methods for iOS plugin, matching Android functionality. Fix compilation errors across plugin files and add comprehensive build/test infrastructure. Key Changes: - Add checkPermissionStatus() and requestNotificationPermissions() methods - Fix 13+ categories of Swift compilation errors (type conversions, logger API, access control, async/await, etc.) - Create DailyNotificationScheduler, DailyNotificationStorage, DailyNotificationStateActor, and DailyNotificationErrorCodes components - Fix CoreData initialization to handle missing model gracefully for Phase 1 - Add iOS test app build script with simulator auto-detection - Update directive with lessons learned from build and permission work Build Status: ✅ BUILD SUCCEEDED Test App: ✅ Ready for iOS Simulator testing Files Modified: - doc/directives/0003-iOS-Android-Parity-Directive.md (lessons learned) - ios/Plugin/DailyNotificationPlugin.swift (Phase 1 methods) - ios/Plugin/DailyNotificationModel.swift (CoreData fix) - 11+ other plugin files (compilation fixes) Files Added: - ios/Plugin/DailyNotificationScheduler.swift - ios/Plugin/DailyNotificationStorage.swift - ios/Plugin/DailyNotificationStateActor.swift - ios/Plugin/DailyNotificationErrorCodes.swift - scripts/build-ios-test-app.sh - scripts/setup-ios-test-app.sh - test-apps/ios-test-app/ (full test app) - Multiple Phase 1 documentation files
This commit is contained in:
618
test-apps/ios-test-app/App/App/Public/index.html
Normal file
618
test-apps/ios-test-app/App/App/Public/index.html
Normal file
@@ -0,0 +1,618 @@
|
||||
<!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">
|
||||
<h1>🔔 DailyNotification Plugin Test</h1>
|
||||
<p>Test the DailyNotification plugin functionality</p>
|
||||
<p style="font-size: 12px; opacity: 0.8;">Build: 2025-10-14 05:00:00 UTC</p>
|
||||
|
||||
<button class="button" onclick="testPlugin()">Test Plugin</button>
|
||||
<button class="button" onclick="configurePlugin()">Configure Plugin</button>
|
||||
<button class="button" onclick="checkStatus()">Check Status</button>
|
||||
|
||||
<h2>🔔 Notification Tests</h2>
|
||||
<button class="button" onclick="testNotification()">Test Notification</button>
|
||||
<button class="button" onclick="scheduleNotification()">Schedule Notification</button>
|
||||
<button class="button" onclick="showReminder()">Show Reminder</button>
|
||||
|
||||
<h2>🔐 Permission Management</h2>
|
||||
<button class="button" onclick="checkPermissions()">Check Permissions</button>
|
||||
<button class="button" onclick="requestPermissions()">Request Permissions</button>
|
||||
<button class="button" onclick="openExactAlarmSettings()">Exact Alarm Settings</button>
|
||||
|
||||
<h2>📢 Channel Management</h2>
|
||||
<button class="button" onclick="checkChannelStatus()">Check Channel Status</button>
|
||||
<button class="button" onclick="openChannelSettings()">Open Channel Settings</button>
|
||||
<button class="button" onclick="checkComprehensiveStatus()">Comprehensive 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;
|
||||
|
||||
// Debug: Log available methods
|
||||
if (window.DailyNotification) {
|
||||
console.log('DailyNotification plugin found');
|
||||
console.log('Available methods:', Object.keys(window.DailyNotification));
|
||||
console.log('checkPermissionStatus type:', typeof window.DailyNotification.checkPermissionStatus);
|
||||
} else {
|
||||
console.error('DailyNotification plugin NOT found');
|
||||
console.log('Available plugins:', Object.keys(window.Capacitor.Plugins || {}));
|
||||
}
|
||||
|
||||
// Define functions immediately and attach to window
|
||||
function testPlugin() {
|
||||
console.log('testPlugin called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Testing plugin...';
|
||||
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;
|
||||
}
|
||||
// Plugin is loaded and ready
|
||||
status.innerHTML = 'Plugin is loaded and ready!';
|
||||
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
|
||||
} catch (error) {
|
||||
status.innerHTML = `Plugin test failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
function configurePlugin() {
|
||||
console.log('configurePlugin called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Configuring plugin...';
|
||||
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;
|
||||
}
|
||||
|
||||
// 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...');
|
||||
// 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(() => {
|
||||
status.innerHTML = 'Plugin configured successfully!<br>✅ Plugin settings<br>✅ Native fetcher (optional for demo)';
|
||||
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
|
||||
})
|
||||
.catch(error => {
|
||||
status.innerHTML = `Configuration failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
status.innerHTML = `Configuration failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
function checkStatus() {
|
||||
console.log('checkStatus called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Checking plugin 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.getNotificationStatus()
|
||||
.then(result => {
|
||||
const nextTime = result.nextNotificationTime ? new Date(result.nextNotificationTime).toLocaleString() : 'None scheduled';
|
||||
status.innerHTML = `Plugin Status:<br>
|
||||
Enabled: ${result.isEnabled}<br>
|
||||
Next Notification: ${nextTime}<br>
|
||||
Pending: ${result.pending}<br>
|
||||
Settings: ${JSON.stringify(result.settings)}`;
|
||||
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
|
||||
})
|
||||
.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
|
||||
}
|
||||
}
|
||||
|
||||
// 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() + 600000); // 10 minutes from now
|
||||
const prefetchTime = new Date(now.getTime() + 300000); // 5 minutes from now
|
||||
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
|
||||
})
|
||||
.catch(error => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleNotification() {
|
||||
console.log('scheduleNotification called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Scheduling notification...';
|
||||
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;
|
||||
}
|
||||
|
||||
// Schedule notification for 10 minutes from now (allows 5 min prefetch to fire)
|
||||
const now = new Date();
|
||||
const notificationTime = new Date(now.getTime() + 600000); // 10 minutes from now
|
||||
const prefetchTime = new Date(now.getTime() + 300000); // 5 minutes from now
|
||||
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: 'Scheduled Notification',
|
||||
body: 'This notification was scheduled 10 minutes ago!',
|
||||
sound: true,
|
||||
priority: 'default'
|
||||
})
|
||||
.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
|
||||
})
|
||||
.catch(error => {
|
||||
status.innerHTML = `Scheduling failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
status.innerHTML = `Scheduling test failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
function showReminder() {
|
||||
console.log('showReminder called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Showing reminder...';
|
||||
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;
|
||||
}
|
||||
|
||||
// Schedule daily reminder using scheduleDailyReminder
|
||||
const now = new Date();
|
||||
const reminderTime = new Date(now.getTime() + 10000); // 10 seconds from now
|
||||
const timeString = reminderTime.getHours().toString().padStart(2, '0') + ':' +
|
||||
reminderTime.getMinutes().toString().padStart(2, '0');
|
||||
|
||||
window.DailyNotification.scheduleDailyReminder({
|
||||
id: 'daily-reminder-test',
|
||||
title: 'Daily Reminder',
|
||||
body: 'Don\'t forget to check your daily notifications!',
|
||||
time: timeString,
|
||||
sound: true,
|
||||
vibration: true,
|
||||
priority: 'default',
|
||||
repeatDaily: false // Just for testing
|
||||
})
|
||||
.then(() => {
|
||||
status.innerHTML = 'Daily reminder scheduled for ' + timeString + '!';
|
||||
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
|
||||
})
|
||||
.catch(error => {
|
||||
status.innerHTML = `Reminder failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
status.innerHTML = `Reminder test failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
// Permission management functions
|
||||
function checkPermissions() {
|
||||
console.log('checkPermissions called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Checking 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;
|
||||
}
|
||||
|
||||
// Check if method exists
|
||||
if (typeof window.DailyNotification.checkPermissionStatus !== 'function') {
|
||||
status.innerHTML = 'checkPermissionStatus method not available. Plugin may need to be rebuilt.';
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
console.error('checkPermissionStatus method not found on DailyNotification plugin');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Calling checkPermissionStatus...');
|
||||
|
||||
// Add timeout wrapper (10 seconds)
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Permission check timed out after 10 seconds')), 10000);
|
||||
});
|
||||
|
||||
Promise.race([
|
||||
window.DailyNotification.checkPermissionStatus(),
|
||||
timeoutPromise
|
||||
])
|
||||
.then(result => {
|
||||
console.log('Permission check result:', result);
|
||||
status.innerHTML = `Permission Status:<br>
|
||||
Notifications: ${result.notificationsEnabled ? '✅' : '❌'}<br>
|
||||
Exact Alarm: ${result.exactAlarmEnabled ? '✅' : '❌'}<br>
|
||||
Wake Lock: ${result.wakeLockEnabled ? '✅' : '❌'}<br>
|
||||
All Granted: ${result.allPermissionsGranted ? '✅' : '❌'}`;
|
||||
status.style.background = result.allPermissionsGranted ?
|
||||
'rgba(0, 255, 0, 0.3)' : 'rgba(255, 165, 0, 0.3)'; // Green or orange
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Permission check error:', error);
|
||||
status.innerHTML = `Permission check failed: ${error.message || error}<br>Check console for details.`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Permission check exception:', error);
|
||||
status.innerHTML = `Permission check failed: ${error.message || error}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
console.error('DailyNotification plugin not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if method exists
|
||||
if (typeof window.DailyNotification.requestNotificationPermissions !== 'function') {
|
||||
status.innerHTML = 'requestNotificationPermissions method not available. Plugin may need to be rebuilt.';
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
console.error('requestNotificationPermissions method not found on DailyNotification plugin');
|
||||
console.log('Available methods:', Object.keys(window.DailyNotification));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🔐 Calling requestNotificationPermissions...');
|
||||
|
||||
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
|
||||
|
||||
// Check permissions again after request
|
||||
setTimeout(() => {
|
||||
checkPermissions();
|
||||
}, 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 openExactAlarmSettings() {
|
||||
console.log('openExactAlarmSettings called');
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Opening exact alarm settings...';
|
||||
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.openExactAlarmSettings()
|
||||
.then(() => {
|
||||
status.innerHTML = 'Exact alarm settings opened! Please enable "Allow exact alarms" and return to the app.';
|
||||
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
|
||||
})
|
||||
.catch(error => {
|
||||
status.innerHTML = `Failed to open exact alarm settings: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
status.innerHTML = `Failed to open exact alarm settings: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
function checkChannelStatus() {
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Checking channel 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.isChannelEnabled()
|
||||
.then(result => {
|
||||
const importanceText = getImportanceText(result.importance);
|
||||
status.innerHTML = `Channel Status: ${result.enabled ? 'Enabled' : 'Disabled'} (${importanceText})`;
|
||||
status.style.background = result.enabled ? 'rgba(0, 255, 0, 0.3)' : 'rgba(255, 0, 0, 0.3)';
|
||||
})
|
||||
.catch(error => {
|
||||
status.innerHTML = `Channel check failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
status.innerHTML = `Channel check failed: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
function openChannelSettings() {
|
||||
const status = document.getElementById('status');
|
||||
status.innerHTML = 'Opening channel settings...';
|
||||
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.openChannelSettings()
|
||||
.then(result => {
|
||||
if (result.opened) {
|
||||
status.innerHTML = 'Channel settings opened! Please enable notifications and return to the app.';
|
||||
status.style.background = 'rgba(0, 255, 0, 0.3)'; // Green background
|
||||
} else {
|
||||
status.innerHTML = 'Could not open channel settings (may not be available on this device)';
|
||||
status.style.background = 'rgba(255, 165, 0, 0.3)'; // Orange background
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
status.innerHTML = `Failed to open channel settings: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
});
|
||||
} catch (error) {
|
||||
status.innerHTML = `Failed to open channel settings: ${error.message}`;
|
||||
status.style.background = 'rgba(255, 0, 0, 0.3)'; // Red background
|
||||
}
|
||||
}
|
||||
|
||||
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.testPlugin = testPlugin;
|
||||
window.configurePlugin = configurePlugin;
|
||||
window.checkStatus = checkStatus;
|
||||
window.testNotification = testNotification;
|
||||
window.scheduleNotification = scheduleNotification;
|
||||
window.showReminder = showReminder;
|
||||
window.checkPermissions = checkPermissions;
|
||||
window.requestPermissions = requestPermissions;
|
||||
window.openExactAlarmSettings = openExactAlarmSettings;
|
||||
window.checkChannelStatus = checkChannelStatus;
|
||||
window.openChannelSettings = openChannelSettings;
|
||||
window.checkComprehensiveStatus = checkComprehensiveStatus;
|
||||
|
||||
console.log('Functions attached to window:', {
|
||||
testPlugin: typeof window.testPlugin,
|
||||
configurePlugin: typeof window.configurePlugin,
|
||||
checkStatus: typeof window.checkStatus,
|
||||
testNotification: typeof window.testNotification,
|
||||
scheduleNotification: typeof window.scheduleNotification,
|
||||
showReminder: typeof window.showReminder
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
93
test-apps/ios-test-app/BUILD_NOTES.md
Normal file
93
test-apps/ios-test-app/BUILD_NOTES.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# iOS Test App Build Notes
|
||||
|
||||
## Build Status
|
||||
|
||||
**Last Build Attempt:** 2025-11-13
|
||||
**Status:** ⚠️ **Build Errors** (Swift compilation issues)
|
||||
|
||||
---
|
||||
|
||||
## Current Issues
|
||||
|
||||
### 1. Swift Compilation Errors
|
||||
|
||||
The build is failing with Swift module compilation errors in `DailyNotificationPlugin`:
|
||||
|
||||
```
|
||||
EmitSwiftModule normal arm64 (in target 'DailyNotificationPlugin' from project 'Pods')
|
||||
SwiftEmitModule normal arm64 Emitting module for DailyNotificationPlugin
|
||||
```
|
||||
|
||||
**Possible Causes:**
|
||||
- Swift version compatibility issues
|
||||
- Missing imports or dependencies
|
||||
- Module visibility issues
|
||||
|
||||
**Next Steps:**
|
||||
1. Check Swift version compatibility
|
||||
2. Verify all plugin dependencies are properly linked
|
||||
3. Review Swift compilation errors in detail
|
||||
|
||||
---
|
||||
|
||||
## Simulator Detection
|
||||
|
||||
**Status:** ✅ **Fixed**
|
||||
|
||||
The build script now auto-detects available iPhone simulators using device IDs (more reliable than names).
|
||||
|
||||
**Available Simulators:**
|
||||
- iPhone 17 Pro
|
||||
- iPhone 17 Pro Max
|
||||
- iPhone 17
|
||||
- iPhone 16e
|
||||
- iPhone Air
|
||||
|
||||
---
|
||||
|
||||
## Build Command
|
||||
|
||||
```bash
|
||||
cd /Users/cloud/dnp
|
||||
./scripts/build-ios-test-app.sh --simulator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### If Build Fails
|
||||
|
||||
1. **Check Swift Errors:**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
xcodebuild build -workspace App.xcworkspace -scheme App -sdk iphonesimulator 2>&1 | grep -i error
|
||||
```
|
||||
|
||||
2. **Clean Build:**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
xcodebuild clean -workspace App.xcworkspace -scheme App
|
||||
rm -rf Pods Podfile.lock
|
||||
~/.rbenv/shims/pod install
|
||||
```
|
||||
|
||||
3. **Check Plugin Dependencies:**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
~/.rbenv/shims/pod install --verbose
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Simulator detection fixed
|
||||
2. ⚠️ Resolve Swift compilation errors
|
||||
3. ⏳ Complete successful build
|
||||
4. ⏳ Test app functionality
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-13
|
||||
|
||||
70
test-apps/ios-test-app/BUILD_SUCCESS.md
Normal file
70
test-apps/ios-test-app/BUILD_SUCCESS.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# iOS Test App Build Success ✅
|
||||
|
||||
**Date:** 2025-11-13
|
||||
**Status:** ✅ **BUILD SUCCEEDED**
|
||||
|
||||
---
|
||||
|
||||
## Build Status
|
||||
|
||||
✅ **All compilation errors fixed**
|
||||
✅ **Build successful for iOS Simulator**
|
||||
✅ **Ready for functional testing**
|
||||
|
||||
---
|
||||
|
||||
## Compilation Errors Fixed
|
||||
|
||||
### Summary
|
||||
|
||||
Fixed **12 categories** of compilation errors:
|
||||
|
||||
1. ✅ Type conversion errors (Int64 → Double)
|
||||
2. ✅ Logger API inconsistencies
|
||||
3. ✅ Immutable property assignments
|
||||
4. ✅ Missing import statements
|
||||
5. ✅ Access control issues
|
||||
6. ✅ Phase 2 features in Phase 1 code
|
||||
7. ✅ iOS API availability checks
|
||||
8. ✅ Switch statement exhaustiveness
|
||||
9. ✅ Variable initialization in closures
|
||||
10. ✅ Capacitor plugin call reject signature
|
||||
11. ✅ Database method naming
|
||||
12. ✅ Async/await in synchronous context
|
||||
|
||||
---
|
||||
|
||||
## Build Command
|
||||
|
||||
```bash
|
||||
./scripts/build-ios-test-app.sh --simulator
|
||||
```
|
||||
|
||||
**Result:** ✅ BUILD SUCCEEDED
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Build successful
|
||||
2. ⏳ Run test app on iOS Simulator
|
||||
3. ⏳ Test Phase 1 methods
|
||||
4. ⏳ Verify notification scheduling
|
||||
5. ⏳ Test background task execution
|
||||
|
||||
---
|
||||
|
||||
## Simulator Detection
|
||||
|
||||
✅ **Working** - Auto-detects available iPhone simulators
|
||||
|
||||
**Example:**
|
||||
```
|
||||
[STEP] Detecting available iPhone simulator...
|
||||
[INFO] Building for iOS Simulator (iPhone 17 Pro, ID: 68D19D08-4701-422C-AF61-2E21ACA1DD4C)...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-13
|
||||
|
||||
97
test-apps/ios-test-app/COMPILATION_FIXES.md
Normal file
97
test-apps/ios-test-app/COMPILATION_FIXES.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# iOS Test App Compilation Fixes
|
||||
|
||||
**Date:** 2025-11-13
|
||||
**Status:** ✅ **COMPILATION ERRORS FIXED**
|
||||
|
||||
---
|
||||
|
||||
## Fixed Compilation Errors
|
||||
|
||||
### 1. Missing Capacitor Import ✅
|
||||
|
||||
**File:** `ios/Plugin/DailyNotificationCallbacks.swift`
|
||||
|
||||
**Error:**
|
||||
```
|
||||
error: cannot find type 'CAPPluginCall' in scope
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
Added `import Capacitor` to the file.
|
||||
|
||||
---
|
||||
|
||||
### 2. Type Conversion Errors (Int64 → Double) ✅
|
||||
|
||||
**Files:**
|
||||
- `ios/Plugin/DailyNotificationTTLEnforcer.swift`
|
||||
- `ios/Plugin/DailyNotificationRollingWindow.swift`
|
||||
|
||||
**Error:**
|
||||
```
|
||||
error: cannot convert value of type 'Int64' to expected argument type 'Double'
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
Changed `Date(timeIntervalSince1970: value / 1000)` to `Date(timeIntervalSince1970: Double(value) / 1000.0)` for all `Int64` timestamp conversions.
|
||||
|
||||
---
|
||||
|
||||
### 3. Logger Method Calls ✅
|
||||
|
||||
**File:** `ios/Plugin/DailyNotificationErrorHandler.swift`
|
||||
|
||||
**Error:**
|
||||
```
|
||||
error: value of type 'DailyNotificationLogger' has no member 'debug'
|
||||
error: value of type 'DailyNotificationLogger' has no member 'error'
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
Changed `logger.debug(tag, message)` to `logger.log(.debug, "\(tag): \(message)")` and similar for error calls.
|
||||
|
||||
---
|
||||
|
||||
### 4. Immutable Property Assignment ✅
|
||||
|
||||
**File:** `ios/Plugin/DailyNotificationBackgroundTaskManager.swift`
|
||||
|
||||
**Error:**
|
||||
```
|
||||
error: cannot assign to property: 'payload' is a 'let' constant
|
||||
error: cannot assign to property: 'fetchedAt' is a 'let' constant
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
Changed from mutating existing `NotificationContent` to creating a new instance with updated values.
|
||||
|
||||
---
|
||||
|
||||
## Simulator Detection ✅
|
||||
|
||||
**Status:** ✅ **WORKING**
|
||||
|
||||
The build script now:
|
||||
- Auto-detects available iPhone simulators
|
||||
- Uses device ID (UUID) for reliable targeting
|
||||
- Falls back to device name if ID extraction fails
|
||||
- Uses generic destination as last resort
|
||||
|
||||
**Example Output:**
|
||||
```
|
||||
[STEP] Detecting available iPhone simulator...
|
||||
[INFO] Building for iOS Simulator (iPhone 17 Pro, ID: 68D19D08-4701-422C-AF61-2E21ACA1DD4C)...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
✅ All compilation errors fixed
|
||||
✅ Simulator detection working
|
||||
⏳ Build verification in progress
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-13
|
||||
|
||||
53
test-apps/ios-test-app/COMPILATION_STATUS.md
Normal file
53
test-apps/ios-test-app/COMPILATION_STATUS.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# iOS Test App Compilation Status
|
||||
|
||||
**Date:** 2025-11-13
|
||||
**Status:** 🔄 **IN PROGRESS** - Fixing compilation errors
|
||||
|
||||
---
|
||||
|
||||
## Compilation Errors Fixed ✅
|
||||
|
||||
1. ✅ **Missing Capacitor Import** - `DailyNotificationCallbacks.swift`
|
||||
2. ✅ **Type Conversion Errors** - `DailyNotificationTTLEnforcer.swift`, `DailyNotificationRollingWindow.swift`
|
||||
3. ✅ **Logger Method Calls** - `DailyNotificationErrorHandler.swift`, `DailyNotificationPerformanceOptimizer.swift`
|
||||
4. ✅ **Immutable Property Assignment** - `DailyNotificationBackgroundTaskManager.swift`
|
||||
5. ✅ **Missing Codable Conformance** - `NotificationContent.swift`
|
||||
6. ✅ **Access Control Issues** - Made `storage`, `stateActor`, `notificationCenter` accessible
|
||||
|
||||
---
|
||||
|
||||
## Remaining Issues
|
||||
|
||||
### Current Errors:
|
||||
- `DailyNotificationBackgroundTasks.swift`: Access to `stateActor` and `storage` (fixed by making them non-private)
|
||||
- Method name mismatch: `maintain()` vs `maintainRollingWindow()` (fixed)
|
||||
|
||||
---
|
||||
|
||||
## Simulator Detection ✅
|
||||
|
||||
**Status:** ✅ **WORKING**
|
||||
|
||||
The build script successfully:
|
||||
- Detects available iPhone simulators
|
||||
- Uses device ID (UUID) for reliable targeting
|
||||
- Falls back gracefully if detection fails
|
||||
|
||||
**Example:**
|
||||
```
|
||||
[STEP] Detecting available iPhone simulator...
|
||||
[INFO] Building for iOS Simulator (iPhone 17 Pro, ID: 68D19D08-4701-422C-AF61-2E21ACA1DD4C)...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Fix remaining compilation errors
|
||||
2. ⏳ Verify build succeeds
|
||||
3. ⏳ Test app functionality
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-13
|
||||
|
||||
119
test-apps/ios-test-app/COMPILATION_SUMMARY.md
Normal file
119
test-apps/ios-test-app/COMPILATION_SUMMARY.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# iOS Test App Compilation Summary
|
||||
|
||||
**Date:** 2025-11-13
|
||||
**Status:** ✅ **BUILD SUCCEEDED**
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Successfully fixed all Swift compilation errors to enable iOS test app building. The build now completes successfully for iOS Simulator.
|
||||
|
||||
---
|
||||
|
||||
## Error Categories Fixed
|
||||
|
||||
### 1. Type System Mismatches ✅
|
||||
- **Files:** `DailyNotificationTTLEnforcer.swift`, `DailyNotificationRollingWindow.swift`
|
||||
- **Fix:** Explicit `Int64` to `Double` conversion for `Date` creation
|
||||
|
||||
### 2. Logger API Inconsistency ✅
|
||||
- **Files:** `DailyNotificationErrorHandler.swift`, `DailyNotificationPerformanceOptimizer.swift`, `DailyNotificationETagManager.swift`
|
||||
- **Fix:** Updated to `logger.log(.level, "\(TAG): message")` format
|
||||
|
||||
### 3. Immutable Property Assignment ✅
|
||||
- **Files:** `DailyNotificationBackgroundTaskManager.swift`
|
||||
- **Fix:** Create new instances instead of mutating `let` properties
|
||||
|
||||
### 4. Missing Imports ✅
|
||||
- **Files:** `DailyNotificationCallbacks.swift`
|
||||
- **Fix:** Added `import Capacitor`
|
||||
|
||||
### 5. Access Control ✅
|
||||
- **Files:** `DailyNotificationPlugin.swift`
|
||||
- **Fix:** Changed `private` to `internal` for extension access
|
||||
|
||||
### 6. Phase 2 Features in Phase 1 ✅
|
||||
- **Files:** `DailyNotificationBackgroundTasks.swift`, `DailyNotificationCallbacks.swift`
|
||||
- **Fix:** Stubbed Phase 2 methods with TODO comments
|
||||
|
||||
### 7. iOS API Availability ✅
|
||||
- **Files:** `DailyNotificationPlugin.swift`
|
||||
- **Fix:** Added `#available(iOS 15.0, *)` checks for `interruptionLevel`
|
||||
|
||||
### 8. Switch Exhaustiveness ✅
|
||||
- **Files:** `DailyNotificationErrorHandler.swift`
|
||||
- **Fix:** Added missing `.scheduling` case
|
||||
|
||||
### 9. Variable Initialization ✅
|
||||
- **Files:** `DailyNotificationErrorHandler.swift`
|
||||
- **Fix:** Extract values from closures before use
|
||||
|
||||
### 10. Capacitor API Signature ✅
|
||||
- **Files:** `DailyNotificationPlugin.swift`
|
||||
- **Fix:** Use `call.reject(message, code)` format
|
||||
|
||||
### 11. Method Naming ✅
|
||||
- **Files:** `DailyNotificationPerformanceOptimizer.swift`
|
||||
- **Fix:** Use `executeSQL()` instead of `execSQL()`
|
||||
|
||||
### 12. Async/Await ✅
|
||||
- **Files:** `DailyNotificationETagManager.swift`
|
||||
- **Fix:** Made functions `async throws` where needed
|
||||
|
||||
### 13. Codable Conformance ✅
|
||||
- **Files:** `NotificationContent.swift`
|
||||
- **Fix:** Added `Codable` protocol conformance
|
||||
|
||||
---
|
||||
|
||||
## Build Verification
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
./scripts/build-ios-test-app.sh --simulator
|
||||
```
|
||||
|
||||
**Result:** ✅ BUILD SUCCEEDED
|
||||
|
||||
**Simulator Detection:** ✅ Working
|
||||
- Auto-detects available iPhone simulators
|
||||
- Uses device ID (UUID) for reliable targeting
|
||||
- Falls back gracefully if detection fails
|
||||
|
||||
---
|
||||
|
||||
## Files Modified
|
||||
|
||||
### Swift Source Files
|
||||
- `ios/Plugin/DailyNotificationPlugin.swift`
|
||||
- `ios/Plugin/DailyNotificationCallbacks.swift`
|
||||
- `ios/Plugin/DailyNotificationErrorHandler.swift`
|
||||
- `ios/Plugin/DailyNotificationETagManager.swift`
|
||||
- `ios/Plugin/DailyNotificationPerformanceOptimizer.swift`
|
||||
- `ios/Plugin/DailyNotificationTTLEnforcer.swift`
|
||||
- `ios/Plugin/DailyNotificationRollingWindow.swift`
|
||||
- `ios/Plugin/DailyNotificationBackgroundTaskManager.swift`
|
||||
- `ios/Plugin/DailyNotificationBackgroundTasks.swift`
|
||||
- `ios/Plugin/DailyNotificationStateActor.swift`
|
||||
- `ios/Plugin/DailyNotificationDatabase.swift`
|
||||
- `ios/Plugin/NotificationContent.swift`
|
||||
|
||||
### Configuration Files
|
||||
- `ios/DailyNotificationPlugin.podspec` (dependency version constraints)
|
||||
- `scripts/build-ios-test-app.sh` (simulator detection)
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Build successful
|
||||
2. ⏳ Run test app on iOS Simulator
|
||||
3. ⏳ Test Phase 1 plugin methods
|
||||
4. ⏳ Verify notification scheduling
|
||||
5. ⏳ Test background task execution
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-13
|
||||
|
||||
130
test-apps/ios-test-app/README.md
Normal file
130
test-apps/ios-test-app/README.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# iOS Test App
|
||||
|
||||
**Status:** ✅ **SETUP COMPLETE**
|
||||
**Ready for:** Building and testing
|
||||
|
||||
---
|
||||
|
||||
## Setup Status
|
||||
|
||||
✅ Basic structure created
|
||||
✅ Capacitor iOS platform added
|
||||
✅ Info.plist configured with BGTask identifiers
|
||||
✅ AppDelegate configured for background tasks
|
||||
✅ Podfile configured with plugin reference
|
||||
⚠️ CocoaPods installation required
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### 1. Install CocoaPods (if not installed)
|
||||
|
||||
```bash
|
||||
sudo gem install cocoapods
|
||||
```
|
||||
|
||||
### 2. Install Pod Dependencies
|
||||
|
||||
```bash
|
||||
cd ios/App
|
||||
pod install
|
||||
cd ../..
|
||||
```
|
||||
|
||||
### 3. Build and Run
|
||||
|
||||
**Option A: Using Build Script**
|
||||
```bash
|
||||
# From repo root
|
||||
./scripts/build-ios-test-app.sh --simulator
|
||||
```
|
||||
|
||||
**Option B: Using Xcode**
|
||||
```bash
|
||||
cd ios/App
|
||||
open App.xcworkspace
|
||||
# Then press Cmd+R in Xcode
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Plugin Registration
|
||||
|
||||
The plugin is registered via:
|
||||
- **Podfile:** `pod 'DailyNotificationPlugin', :path => '../../../ios/Plugin'`
|
||||
- **Capacitor Config:** `capacitor.config.json` includes plugin entry
|
||||
- **AppDelegate:** Background tasks registered
|
||||
|
||||
---
|
||||
|
||||
## Configuration Files
|
||||
|
||||
- **Info.plist:** Configured with BGTask identifiers and background modes
|
||||
- **AppDelegate.swift:** Background task registration added
|
||||
- **Podfile:** Plugin reference added
|
||||
- **capacitor.config.json:** Plugin enabled
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CocoaPods Not Installed
|
||||
|
||||
**Error:** `command not found: pod`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
sudo gem install cocoapods
|
||||
```
|
||||
|
||||
### Plugin Not Found
|
||||
|
||||
**Error:** Build fails with plugin not found
|
||||
|
||||
**Solution:**
|
||||
1. Verify plugin exists at `../../../ios/Plugin/`
|
||||
2. Run `pod install` in `ios/App/` directory
|
||||
3. Clean build folder in Xcode (Cmd+Shift+K)
|
||||
|
||||
### Build Failures
|
||||
|
||||
**Solution:**
|
||||
1. Run `pod install` in `ios/App/` directory
|
||||
2. Clean build folder (Cmd+Shift+K)
|
||||
3. Verify Capacitor plugin path
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
ios-test-app/
|
||||
├── ios/
|
||||
│ └── App/
|
||||
│ ├── App.xcworkspace # Open this in Xcode
|
||||
│ ├── Podfile # CocoaPods dependencies
|
||||
│ └── App/
|
||||
│ ├── AppDelegate.swift # Background task registration
|
||||
│ ├── Info.plist # BGTask identifiers configured
|
||||
│ └── public/
|
||||
│ └── index.html # Test UI
|
||||
├── App/
|
||||
│ └── App/
|
||||
│ └── Public/
|
||||
│ └── index.html # Source HTML
|
||||
└── capacitor.config.json # Capacitor configuration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **Requirements:** `doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md`
|
||||
- **Testing Guide:** `doc/IOS_PHASE1_TESTING_GUIDE.md`
|
||||
- **Build Script:** `scripts/build-ios-test-app.sh`
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ **READY FOR BUILDING** (after CocoaPods installation)
|
||||
|
||||
104
test-apps/ios-test-app/SETUP_COMPLETE.md
Normal file
104
test-apps/ios-test-app/SETUP_COMPLETE.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# iOS Test App Setup Complete ✅
|
||||
|
||||
**Date:** 2025-01-XX
|
||||
**Status:** ✅ **READY FOR BUILDING AND TESTING**
|
||||
|
||||
---
|
||||
|
||||
## ✅ Setup Complete
|
||||
|
||||
All setup steps have been completed successfully:
|
||||
|
||||
1. ✅ **Directory Structure Created**
|
||||
- `test-apps/ios-test-app/` created
|
||||
- Capacitor iOS platform added
|
||||
|
||||
2. ✅ **Configuration Files**
|
||||
- `Info.plist` - BGTask identifiers and background modes configured
|
||||
- `AppDelegate.swift` - Background task registration added
|
||||
- `Podfile` - Plugin reference added and dependencies resolved
|
||||
- `capacitor.config.json` - Plugin enabled
|
||||
|
||||
3. ✅ **CocoaPods Dependencies Installed**
|
||||
- Capacitor 5.7.8
|
||||
- CapacitorCordova 5.7.8
|
||||
- DailyNotificationPlugin 1.0.0
|
||||
|
||||
4. ✅ **Build Script Updated**
|
||||
- Handles rbenv CocoaPods path
|
||||
- Environment checks configured
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Next Steps
|
||||
|
||||
### Build and Run
|
||||
|
||||
**Option A: Using Build Script**
|
||||
```bash
|
||||
cd /Users/cloud/dnp
|
||||
./scripts/build-ios-test-app.sh --simulator
|
||||
```
|
||||
|
||||
**Option B: Using Xcode**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
open App.xcworkspace
|
||||
# Press Cmd+R to build and run
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 Key Files
|
||||
|
||||
- **Workspace:** `test-apps/ios-test-app/ios/App/App.xcworkspace`
|
||||
- **Podfile:** `test-apps/ios-test-app/ios/App/Podfile`
|
||||
- **Info.plist:** `test-apps/ios-test-app/ios/App/App/Info.plist`
|
||||
- **AppDelegate:** `test-apps/ios-test-app/ios/App/App/AppDelegate.swift`
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Build Errors
|
||||
|
||||
If you encounter build errors:
|
||||
|
||||
1. **Clean Build Folder:**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
xcodebuild clean -workspace App.xcworkspace -scheme App
|
||||
```
|
||||
|
||||
2. **Reinstall Pods:**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
rm -rf Pods Podfile.lock
|
||||
~/.rbenv/shims/pod install
|
||||
```
|
||||
|
||||
3. **Sync Capacitor:**
|
||||
```bash
|
||||
cd test-apps/ios-test-app
|
||||
npx cap sync ios
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification Checklist
|
||||
|
||||
- [x] iOS test app directory exists
|
||||
- [x] Capacitor iOS platform added
|
||||
- [x] Info.plist configured
|
||||
- [x] AppDelegate configured
|
||||
- [x] Podfile configured
|
||||
- [x] CocoaPods dependencies installed
|
||||
- [x] Build script updated
|
||||
- [ ] Build successful
|
||||
- [ ] App runs on simulator
|
||||
- [ ] Plugin loads correctly
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ **READY FOR BUILDING**
|
||||
|
||||
121
test-apps/ios-test-app/SETUP_STATUS.md
Normal file
121
test-apps/ios-test-app/SETUP_STATUS.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# iOS Test App Setup Status
|
||||
|
||||
**Date:** 2025-01-XX
|
||||
**Status:** ✅ **STRUCTURE CREATED - READY FOR COCOAPODS**
|
||||
|
||||
---
|
||||
|
||||
## ✅ Completed Steps
|
||||
|
||||
1. ✅ **Directory Structure Created**
|
||||
- `test-apps/ios-test-app/` created
|
||||
- Basic Capacitor structure initialized
|
||||
|
||||
2. ✅ **Capacitor iOS Platform Added**
|
||||
- `npx cap add ios` completed successfully
|
||||
- Xcode project created at `ios/App/App.xcworkspace`
|
||||
|
||||
3. ✅ **HTML Copied**
|
||||
- Android test app HTML copied to `App/App/Public/index.html`
|
||||
- Also synced to `ios/App/App/public/index.html`
|
||||
|
||||
4. ✅ **Info.plist Configured**
|
||||
- BGTask identifiers added
|
||||
- Background modes added
|
||||
- Notification permission description added
|
||||
|
||||
5. ✅ **AppDelegate Configured**
|
||||
- Background task registration added
|
||||
- BGTaskScheduler handlers registered
|
||||
|
||||
6. ✅ **Podfile Configured**
|
||||
- Plugin reference added: `pod 'DailyNotificationPlugin', :path => '../../../../ios'`
|
||||
- Capacitor dependencies included
|
||||
|
||||
7. ✅ **Capacitor Config**
|
||||
- `capacitor.config.json` created
|
||||
- Plugin enabled in config
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Remaining Steps
|
||||
|
||||
### 1. Install CocoaPods (Required)
|
||||
|
||||
```bash
|
||||
sudo gem install cocoapods
|
||||
```
|
||||
|
||||
### 2. Install Pod Dependencies
|
||||
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
pod install
|
||||
```
|
||||
|
||||
This will:
|
||||
- Install Capacitor dependencies
|
||||
- Link DailyNotificationPlugin
|
||||
- Create/update Pods project
|
||||
|
||||
### 3. Build and Run
|
||||
|
||||
**Option A: Build Script**
|
||||
```bash
|
||||
# From repo root
|
||||
./scripts/build-ios-test-app.sh --simulator
|
||||
```
|
||||
|
||||
**Option B: Xcode**
|
||||
```bash
|
||||
cd test-apps/ios-test-app/ios/App
|
||||
open App.xcworkspace
|
||||
# Press Cmd+R to build and run
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
test-apps/ios-test-app/
|
||||
├── ios/
|
||||
│ └── App/
|
||||
│ ├── App.xcworkspace ✅ Created (open this in Xcode)
|
||||
│ ├── Podfile ✅ Configured
|
||||
│ └── App/
|
||||
│ ├── AppDelegate.swift ✅ Background tasks registered
|
||||
│ ├── Info.plist ✅ BGTask identifiers added
|
||||
│ └── public/
|
||||
│ └── index.html ✅ Test UI copied
|
||||
├── App/
|
||||
│ └── App/
|
||||
│ └── Public/
|
||||
│ └── index.html ✅ Source HTML
|
||||
├── capacitor.config.json ✅ Created
|
||||
└── package.json ✅ Created
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Plugin Registration
|
||||
|
||||
The plugin will be registered when CocoaPods installs:
|
||||
|
||||
1. **Podfile** references plugin: `pod 'DailyNotificationPlugin', :path => '../../../../ios'`
|
||||
2. **Podspec** defines plugin: `ios/DailyNotificationPlugin.podspec`
|
||||
3. **Capacitor** auto-detects plugin via `@objc(DailyNotificationPlugin)` annotation
|
||||
4. **JavaScript** bridge created during `npx cap sync ios`
|
||||
|
||||
---
|
||||
|
||||
## Next Actions
|
||||
|
||||
1. **Install CocoaPods** (if not installed)
|
||||
2. **Run `pod install`** in `ios/App/` directory
|
||||
3. **Build and test** using build script or Xcode
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ **READY FOR COCOAPODS INSTALLATION**
|
||||
|
||||
13
test-apps/ios-test-app/capacitor.config.json
Normal file
13
test-apps/ios-test-app/capacitor.config.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"appId": "com.timesafari.dailynotification.test",
|
||||
"appName": "DailyNotification Test App",
|
||||
"webDir": "App/App/Public",
|
||||
"server": {
|
||||
"iosScheme": "capacitor"
|
||||
},
|
||||
"plugins": {
|
||||
"DailyNotification": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
13
test-apps/ios-test-app/ios/.gitignore
vendored
Normal file
13
test-apps/ios-test-app/ios/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
App/build
|
||||
App/Pods
|
||||
App/output
|
||||
App/App/public
|
||||
DerivedData
|
||||
xcuserdata
|
||||
|
||||
# Cordova plugins for Capacitor
|
||||
capacitor-cordova-ios-plugins
|
||||
|
||||
# Generated Config files
|
||||
App/App/capacitor.config.json
|
||||
App/App/config.xml
|
||||
406
test-apps/ios-test-app/ios/App/App.xcodeproj/project.pbxproj
Normal file
406
test-apps/ios-test-app/ios/App/App.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,406 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
|
||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
|
||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
|
||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
|
||||
504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
|
||||
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
|
||||
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
|
||||
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
|
||||
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
|
||||
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
504EC3011FED79650016851F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC2FB1FED79650016851F = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504EC3061FED79650016851F /* App */,
|
||||
504EC3051FED79650016851F /* Products */,
|
||||
7F8756D8B27F46E3366F6CEA /* Pods */,
|
||||
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3051FED79650016851F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504EC3041FED79650016851F /* App.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3061FED79650016851F /* App */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||
504EC30B1FED79650016851F /* Main.storyboard */,
|
||||
504EC30E1FED79650016851F /* Assets.xcassets */,
|
||||
504EC3101FED79650016851F /* LaunchScreen.storyboard */,
|
||||
504EC3131FED79650016851F /* Info.plist */,
|
||||
2FAD9762203C412B000D30F8 /* config.xml */,
|
||||
50B271D01FEDC1A000F3C39B /* public */,
|
||||
);
|
||||
path = App;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7F8756D8B27F46E3366F6CEA /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */,
|
||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
504EC3031FED79650016851F /* App */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */;
|
||||
buildPhases = (
|
||||
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */,
|
||||
504EC3001FED79650016851F /* Sources */,
|
||||
504EC3011FED79650016851F /* Frameworks */,
|
||||
504EC3021FED79650016851F /* Resources */,
|
||||
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = App;
|
||||
productName = App;
|
||||
productReference = 504EC3041FED79650016851F /* App.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
504EC2FC1FED79650016851F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0920;
|
||||
TargetAttributes = {
|
||||
504EC3031FED79650016851F = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 504EC2FB1FED79650016851F;
|
||||
productRefGroup = 504EC3051FED79650016851F /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
504EC3031FED79650016851F /* App */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
504EC3021FED79650016851F /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
|
||||
50B271D11FEDC1A000F3C39B /* public in Resources */,
|
||||
504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
|
||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
|
||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */,
|
||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
504EC3001FED79650016851F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
504EC30B1FED79650016851F /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
504EC30C1FED79650016851F /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3101FED79650016851F /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
504EC3111FED79650016851F /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
504EC3141FED79650016851F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
504EC3151FED79650016851F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
504EC3171FED79650016851F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.timesafari.dailynotification.test;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
504EC3181FED79650016851F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.timesafari.dailynotification.test;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
504EC3141FED79650016851F /* Debug */,
|
||||
504EC3151FED79650016851F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
504EC3171FED79650016851F /* Debug */,
|
||||
504EC3181FED79650016851F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 504EC2FC1FED79650016851F /* Project object */;
|
||||
}
|
||||
7
test-apps/ios-test-app/ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
test-apps/ios-test-app/ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:App.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
10
test-apps/ios-test-app/ios/App/App.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
test-apps/ios-test-app/ios/App/App.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:App.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
69
test-apps/ios-test-app/ios/App/App/AppDelegate.swift
Normal file
69
test-apps/ios-test-app/ios/App/App/AppDelegate.swift
Normal file
@@ -0,0 +1,69 @@
|
||||
import UIKit
|
||||
import Capacitor
|
||||
import BackgroundTasks
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
// Background task identifiers
|
||||
private let fetchTaskIdentifier = "com.timesafari.dailynotification.fetch"
|
||||
private let notifyTaskIdentifier = "com.timesafari.dailynotification.notify"
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Register background tasks
|
||||
if #available(iOS 13.0, *) {
|
||||
BGTaskScheduler.shared.register(forTaskWithIdentifier: fetchTaskIdentifier, using: nil) { task in
|
||||
// Background fetch task handler
|
||||
// Plugin will handle this
|
||||
task.setTaskCompleted(success: true)
|
||||
}
|
||||
|
||||
BGTaskScheduler.shared.register(forTaskWithIdentifier: notifyTaskIdentifier, using: nil) { task in
|
||||
// Background notify task handler
|
||||
// Plugin will handle this
|
||||
task.setTaskCompleted(success: true)
|
||||
}
|
||||
}
|
||||
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
|
||||
// Called when the app was launched with a url. Feel free to add additional processing here,
|
||||
// but if you want the App API to support tracking app url opens, make sure to keep this call
|
||||
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
||||
// Called when the app was launched with an activity, including Universal Links.
|
||||
// Feel free to add additional processing here, but if you want the App API to support
|
||||
// tracking app url opens, make sure to keep this call
|
||||
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "AppIcon-512@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
23
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
vendored
Normal file
23
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732-2.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
vendored
Normal file
BIN
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
vendored
Normal file
BIN
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
vendored
Normal file
BIN
test-apps/ios-test-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17132" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17105"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<imageView key="view" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Splash" id="snD-IY-ifK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
</imageView>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Splash" width="1366" height="1366"/>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14111" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Bridge View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
65
test-apps/ios-test-app/ios/App/App/Info.plist
Normal file
65
test-apps/ios-test-app/ios/App/App/Info.plist
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>DailyNotification Test App</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
<!-- Background Task Identifiers -->
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.timesafari.dailynotification.fetch</string>
|
||||
<string>com.timesafari.dailynotification.notify</string>
|
||||
</array>
|
||||
<!-- Background Modes -->
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>background-fetch</string>
|
||||
<string>background-processing</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<!-- Notification Permissions -->
|
||||
<key>NSUserNotificationsUsageDescription</key>
|
||||
<string>This app uses notifications to deliver daily updates and reminders.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
28
test-apps/ios-test-app/ios/App/Podfile
Normal file
28
test-apps/ios-test-app/ios/App/Podfile
Normal file
@@ -0,0 +1,28 @@
|
||||
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
|
||||
platform :ios, '13.0'
|
||||
use_frameworks!
|
||||
|
||||
# workaround to avoid Xcode caching of Pods that requires
|
||||
# Product -> Clean Build Folder after new Cordova plugins installed
|
||||
# Requires CocoaPods 1.6 or newer
|
||||
install! 'cocoapods', :disable_input_output_paths => true
|
||||
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||
|
||||
end
|
||||
|
||||
# Daily Notification Plugin (local development)
|
||||
# Path: test-apps/ios-test-app/ios/App/ -> ../../../../ios (contains DailyNotificationPlugin.podspec)
|
||||
pod 'DailyNotificationPlugin', :path => '../../../../ios'
|
||||
|
||||
target 'App' do
|
||||
capacitor_pods
|
||||
# Add your Pods here
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
assertDeploymentTarget(installer)
|
||||
end
|
||||
1145
test-apps/ios-test-app/package-lock.json
generated
Normal file
1145
test-apps/ios-test-app/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
test-apps/ios-test-app/package.json
Normal file
14
test-apps/ios-test-app/package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "ios-test-app",
|
||||
"version": "1.0.0",
|
||||
"description": "iOS test app for DailyNotification plugin",
|
||||
"scripts": {
|
||||
"sync": "npx cap sync ios",
|
||||
"open": "npx cap open ios"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor/core": "^5.0.0",
|
||||
"@capacitor/ios": "^5.0.0",
|
||||
"@capacitor/cli": "^5.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user