Browse Source

feat: implement core notification functionality for iOS and Android - Add settings management, proper error handling, and platform-specific implementations

master
Server 5 days ago
parent
commit
9994db28bd
  1. 523
      README.md
  2. 17
      android/app/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java
  3. 16
      ios/DailyNotificationPlugin.podspec
  4. 570
      ios/DailyNotificationPlugin.xcodeproj/project.pbxproj
  5. 7
      ios/DailyNotificationPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  6. 103
      ios/DailyNotificationPlugin.xcodeproj/xcshareddata/xcschemes/DailyNotificationPlugin.xcscheme
  7. 99
      ios/DailyNotificationPlugin.xcodeproj/xcshareddata/xcschemes/DailyNotificationPluginTests.xcscheme
  8. 10
      ios/DailyNotificationPlugin.xcworkspace/contents.xcworkspacedata
  9. BIN
      ios/DailyNotificationPlugin.xcworkspace/xcuserdata/cloud.xcuserdatad/UserInterfaceState.xcuserstate
  10. 31
      ios/Plugin/DailyNotificationConfig.swift
  11. 52
      ios/Plugin/DailyNotificationConstants.swift
  12. 50
      ios/Plugin/DailyNotificationError.swift
  13. 44
      ios/Plugin/DailyNotificationLogger.swift
  14. 253
      ios/Plugin/DailyNotificationPlugin.swift
  15. 19
      ios/Podfile
  16. 29
      ios/Podfile.lock
  17. 29
      ios/Tests/DailyNotificationTests.swift
  18. 52
      ios/project.yml
  19. 12
      package-lock.json
  20. 3
      package.json

523
README.md

@ -1,510 +1,143 @@
# Daily Notification Plugin for Capacitor
A powerful Capacitor plugin for scheduling and managing daily notifications with advanced features like timezone support, offline capabilities, and retry logic.
A Capacitor plugin for scheduling and managing daily notifications with advanced features and robust error handling.
## Features
- Schedule daily notifications at specific times
- Support for multiple notification schedules
- Schedule daily notifications with custom time and content
- Support for different priority levels
- Timezone-aware scheduling
- Offline support with content caching
- Retry logic with exponential backoff
- Custom notification content handlers
- Event-based notification handling
- Comprehensive settings management
- TypeScript support with full type definitions
- Offline support with caching
- Comprehensive permission handling
- Automatic retry logic
- Detailed notification status tracking
- Configurable settings management
## Installation
```bash
npm install @timesafari/daily-notification-plugin
npm install daily-notification-plugin
npx cap sync
```
## iOS Setup
No additional setup required for iOS. The plugin automatically handles all necessary configurations.
## Usage
### Basic Usage
```typescript
import { DailyNotification } from '@timesafari/daily-notification-plugin';
const plugin = new DailyNotification();
import { DailyNotification } from 'daily-notification-plugin';
// Schedule a daily notification
await plugin.scheduleDailyNotification({
await DailyNotification.scheduleDailyNotification({
url: 'https://api.example.com/updates',
time: '09:00',
title: 'Daily Update',
body: 'Your daily content is ready!',
sound: true,
priority: 'high'
body: 'Your daily update is ready'
});
```
### Advanced Features
// Get notification status
const status = await plugin.getNotificationStatus();
console.log('Next notification:', status.nextNotificationTime);
#### Custom Priority
// Handle notification events
plugin.on('notification', (event) => {
console.log('Notification received:', event.detail);
```typescript
await DailyNotification.scheduleDailyNotification({
url: 'https://api.example.com/updates',
time: '09:00',
priority: 'high'
});
```
### Advanced Usage
#### Timezone Support
```typescript
// Multiple schedules with different timezones
const schedules = [
{
url: 'https://api.example.com/morning',
time: '09:00',
timezone: 'America/New_York',
title: 'Morning Update'
},
{
url: 'https://api.example.com/evening',
time: '18:00',
timezone: 'Europe/London',
title: 'Evening Update'
}
];
for (const schedule of schedules) {
await plugin.scheduleDailyNotification(schedule);
}
// Offline support with caching
await plugin.scheduleDailyNotification({
await DailyNotification.scheduleDailyNotification({
url: 'https://api.example.com/updates',
time: '10:00',
offlineFallback: true,
cacheDuration: 3600, // 1 hour
contentHandler: async (response) => {
const data = await response.json();
return {
title: data.title,
body: data.content,
data: data.metadata
};
}
time: '09:00',
timezone: 'America/New_York'
});
```
#### Check Notification Status
// Update settings
await plugin.updateSettings({
time: '11:00',
```typescript
const status = await DailyNotification.getNotificationStatus();
console.log('Notification status:', status);
```
#### Update Settings
```typescript
await DailyNotification.updateSettings({
sound: true,
priority: 'high',
timezone: 'America/Chicago'
timezone: 'America/Los_Angeles'
});
```
## API Reference
## API Documentation
### Methods
#### `scheduleDailyNotification(options: NotificationOptions): Promise<void>`
#### scheduleDailyNotification(options: ScheduleOptions)
Schedule a new daily notification.
Schedules a daily notification with the specified options.
#### getLastNotification()
Get information about the last delivered notification.
```typescript
interface NotificationOptions {
url: string;
time: string; // "HH:mm" format
title?: string;
body?: string;
sound?: boolean;
vibrate?: boolean;
priority?: 'low' | 'normal' | 'high';
retryCount?: number;
retryInterval?: number;
cacheDuration?: number;
headers?: Record<string, string>;
offlineFallback?: boolean;
timezone?: string;
contentHandler?: (response: Response) => Promise<{
title: string;
body: string;
data?: any;
}>;
}
```
#### `getLastNotification(): Promise<NotificationResponse | null>`
Retrieves the last notification that was delivered.
#### `cancelAllNotifications(): Promise<void>`
#### cancelAllNotifications()
Cancel all pending notifications.
Cancels all scheduled notifications.
#### getNotificationStatus()
Get current notification status and settings.
#### `getNotificationStatus(): Promise<NotificationStatus>`
#### updateSettings(settings: NotificationSettings)
Update notification settings.
Gets the current status of notifications.
#### checkPermissions()
Check current notification permissions.
#### `updateSettings(settings: NotificationSettings): Promise<void>`
#### requestPermissions()
Request notification permissions.
Updates notification settings.
### Types
```typescript
interface NotificationSettings {
time?: string;
interface ScheduleOptions {
url: string;
time: string;
title?: string;
body?: string;
sound?: boolean;
vibrate?: boolean;
priority?: 'low' | 'normal' | 'high';
priority?: 'high' | 'default' | 'low';
timezone?: string;
}
```
### Events
The plugin emits the following events:
- `notification`: Fired when a notification is received or interacted with
```typescript
interface NotificationEvent extends Event {
detail: {
id: string;
action: string;
data?: any;
};
interface NotificationSettings {
sound?: boolean;
priority?: string;
timezone?: string;
}
```
## Testing
The plugin includes comprehensive tests covering:
- Basic functionality
- Multiple schedules
- Timezone handling
- Offline support
- Retry logic
- Event handling
- Settings management
Run tests with:
```bash
npm test
```
## Security Considerations
- All network requests use HTTPS
- Content is validated before display
- Sensitive data is not stored in logs
- Permissions are properly managed
- Input validation is performed on all methods
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Author
Matthew Raymer
## Platform-Specific Implementation
### Android Implementation
- Uses `WorkManager` for periodic data fetching
- Implements `AlarmManager` for precise notification scheduling
- Stores data in `SharedPreferences`
- Handles Doze mode and battery optimizations
### iOS
- Utilizes `BGTaskScheduler` for background fetches
- Implements `UNUserNotificationCenter` for notifications
- Stores data in `UserDefaults`
- Respects system background execution limits
## Permissions
### Android Permissions
Required permissions in `AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
```
### iOS Implementation
- Notification permissions (requested at runtime)
- Background App Refresh capability (enabled in Xcode)
## Error Handling
The plugin implements comprehensive error handling:
- Network failure retry logic with exponential backoff
- Fallback to cached content when fetching fails
- Detailed error logging and reporting
- Graceful degradation when permissions are denied
## Best Practices
### Content Management
- Keep notification content concise and actionable
- Use clear, engaging titles under 50 characters
- Limit notification body to 2-3 lines
- Include a clear call-to-action when appropriate
### Network Optimization
- Implement proper caching headers on your API
- Use compression for network responses
- Keep payload size under 4KB for optimal performance
- Implement rate limiting on your API endpoints
### Battery Considerations
- Schedule notifications during active hours
- Avoid excessive background fetches
- Use appropriate fetch intervals (minimum 15 minutes)
- Implement smart retry strategies
### User Experience
- Request notification permissions at an appropriate time
- Provide clear value proposition for notifications
- Allow users to customize notification timing
- Implement proper error messaging for users
### Security
- Always use HTTPS for API endpoints
- Implement proper API authentication
- Sanitize notification content
- Follow platform-specific security guidelines
### Testing
- Test notifications in various app states
- Verify behavior with different network conditions
- Test on multiple device types and OS versions
- Implement proper error logging for debugging
## Development Setup
### Prerequisites
1. Node.js 14 or higher
2. Java 11 or higher
3. Android Studio and Android SDK
4. Xcode (for iOS development, macOS only)
5. CocoaPods (for iOS development)
### Environment Setup
1. Clone the repository:
```bash
git clone https://github.com/yourusername/capacitor-daily-notification.git
cd capacitor-daily-notification
```
2. Install dependencies:
```bash
npm install
```
This will:
- Install Node.js dependencies
- Check your development environment
- Set up native build environments
- Install platform-specific dependencies
### Building the Plugin
#### TypeScript Build
```bash
# Build TypeScript code
npm run build
# Watch mode for development
npm run watch
```
#### Android Build
```bash
# Build Android library
npm run build:android
# Run Android tests
npm run test:android
```
The Android build will:
1. Compile the TypeScript code
2. Build the Android library
3. Generate an AAR file in `android/build/outputs/aar/`
#### iOS Build
```bash
# Build iOS library
npm run build:ios
# Run iOS tests
npm run test:ios
```
The iOS build will:
1. Compile the TypeScript code
2. Install CocoaPods dependencies
3. Build the iOS framework
### Using in a Capacitor App
1. Install the plugin in your Capacitor app:
```bash
npm install capacitor-daily-notification
```
2. Add to your Android app's `android/app/build.gradle`:
```gradle
dependencies {
implementation project(':daily-notification')
}
```
3. Add to your iOS app's `ios/App/Podfile`:
```ruby
pod 'CapacitorDailyNotification', :path => '../node_modules/capacitor-daily-notification'
```
4. Sync native projects:
```bash
npx cap sync
```
### Troubleshooting
#### Android Issues
1. Gradle Sync Failed
```bash
cd android
./gradlew clean
./gradlew --refresh-dependencies
```
2. Missing Android SDK
- Set ANDROID_HOME environment variable
- Install required SDK components via Android Studio
3. Build Errors
- Check Android Studio for detailed error messages
- Ensure all required SDK components are installed
- Verify Gradle version compatibility
#### iOS Issues
1. Pod Install Failed
```bash
cd ios
pod deintegrate
pod cache clean --all
pod install
```
2. Xcode Build Errors
- Open Xcode project in Xcode
- Check build settings
- Verify deployment target matches requirements
3. Missing Dependencies
- Ensure CocoaPods is installed
- Run `pod setup` to update CocoaPods repos
### Development Workflow
1. Make changes to TypeScript code
2. Run `npm run build` to compile
3. Run `npm run build:native` to build native code
4. Test changes:
- Android: `npm run test:android`
- iOS: `npm run test:ios`
5. Run full validation:
- Android: `npm run validate`
- iOS: `npm run validate:ios`
### Continuous Integration
The plugin includes pre-commit hooks and CI configurations:
1. Pre-commit checks:
- TypeScript compilation
- Linting
- Native build verification
2. CI pipeline:
- Environment validation
- TypeScript build
- Native builds
- Unit tests
- Integration tests
The plugin provides detailed error messages for various scenarios:
- Invalid parameters
- Permission issues
- Scheduling failures
- Invalid time formats
- Invalid timezone identifiers
- Invalid priority values
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our GitHub repository.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Author
Matthew Raymer
## Plugin Security
This plugin follows security best practices:
- Secure storage of sensitive data
- HTTPS-only network requests
- Permission-based access control
- Regular security audits
- No sensitive data in logs
## Support
For support, please open an issue in the GitHub repository or contact the maintainers.
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for a list of changes and version history.
MIT License - see LICENSE file for details

17
android/app/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java

@ -13,6 +13,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
@ -35,6 +36,8 @@ public class DailyNotificationPlugin extends Plugin {
private NotificationManager notificationManager;
private AlarmManager alarmManager;
private Context context;
private SharedPreferences settings;
private static final String SETTINGS_KEY = "daily_notification_settings";
@Override
public void load() {
@ -42,6 +45,7 @@ public class DailyNotificationPlugin extends Plugin {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
createNotificationChannel();
settings = context.getSharedPreferences(SETTINGS_KEY, Context.MODE_PRIVATE);
}
private void createNotificationChannel() {
@ -154,7 +158,18 @@ public class DailyNotificationPlugin extends Plugin {
@PluginMethod
public void updateSettings(PluginCall call) {
// TODO: Implement settings update
SharedPreferences.Editor editor = settings.edit();
if (call.hasOption("timezone")) {
String timezone = call.getString("timezone");
if (TimeZone.getTimeZone(timezone) != null) {
editor.putString("timezone", timezone);
} else {
call.reject("Invalid timezone");
return;
}
}
// Add other settings...
editor.apply();
call.resolve();
}
}

16
ios/DailyNotificationPlugin.podspec

@ -0,0 +1,16 @@
Pod::Spec.new do |s|
s.name = 'DailyNotificationPlugin'
s.version = '1.0.0'
s.summary = 'Daily notification plugin for Capacitor'
s.license = 'MIT'
s.homepage = 'https://github.com/timesafari/daily-notification-plugin'
s.author = 'TimeSafari'
s.source = { :git => 'https://github.com/timesafari/daily-notification-plugin.git', :tag => s.version.to_s }
s.source_files = 'Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
s.ios.deployment_target = '13.0'
s.dependency 'Capacitor'
s.dependency 'CapacitorCordova'
s.swift_version = '5.1'
s.module_name = 'DailyNotificationPlugin'
s.static_framework = true
end

570
ios/DailyNotificationPlugin.xcodeproj/project.pbxproj

@ -0,0 +1,570 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
0C773ACB32780E104F9F24C8 /* DailyNotificationPlugin.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3323D7F1B3ED08FAA559D317 /* DailyNotificationPlugin.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2B7E978FB6B43664754FC9BB /* DailyNotificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6495D32429F76744DC98B457 /* DailyNotificationTests.swift */; };
3C8161B717E367A8B88111BF /* DailyNotificationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC45ABFC1A903AE6233B13F /* DailyNotificationConfig.swift */; };
5898E89B868436827E1E06DF /* DailyNotificationPlugin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3323D7F1B3ED08FAA559D317 /* DailyNotificationPlugin.framework */; };
6C1E173CC70849A66F85B12C /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEB96E881144AB9DBCDF17 /* README.md */; };
74067B7FB473F9455DABAA30 /* Pods_DailyNotificationPlugin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BD2A2F1CA91755E648A5D57 /* Pods_DailyNotificationPlugin.framework */; };
8640E8860A5334043F24DC54 /* Pods_DailyNotificationPluginTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A49F9F065B6559C77DE3BD5 /* Pods_DailyNotificationPluginTests.framework */; };
92CCC02492ECD5CADABE7BC4 /* DailyNotificationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC43315277A65E01BD1B352F /* DailyNotificationError.swift */; };
C194055B816EA1C2DCF17BD2 /* DailyNotificationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = A645658475F4138A9256D485 /* DailyNotificationPlugin.swift */; };
DBCD22D6FACC2C730D7C2911 /* DailyNotificationLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467AB34F611231718368D768 /* DailyNotificationLogger.swift */; };
F86B65B48D5B072F30F76479 /* index.ts in Resources */ = {isa = PBXBuildFile; fileRef = A73A4B8720F98987381BAECF /* index.ts */; };
FB9C99C0B426E0109ED1218C /* DailyNotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9237F98BBE39C5667CCCF78C /* DailyNotificationConstants.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
AE616C66C793C36141ED183E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 006593AF8D5F74184E8E7C52 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 257C4D3AD8FBFC25B796808A;
remoteInfo = DailyNotificationPlugin;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
4943F65747C3ABB97AEBDDB9 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
0C773ACB32780E104F9F24C8 /* DailyNotificationPlugin.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A49F9F065B6559C77DE3BD5 /* Pods_DailyNotificationPluginTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DailyNotificationPluginTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2DDEB96E881144AB9DBCDF17 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
3323D7F1B3ED08FAA559D317 /* DailyNotificationPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DailyNotificationPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3BD2A2F1CA91755E648A5D57 /* Pods_DailyNotificationPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DailyNotificationPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
40B0BB9ACA2D2A1BEB4DF9A2 /* Pods-DailyNotificationPluginTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DailyNotificationPluginTests.debug.xcconfig"; path = "Target Support Files/Pods-DailyNotificationPluginTests/Pods-DailyNotificationPluginTests.debug.xcconfig"; sourceTree = "<group>"; };
4494D62E3E3D3A7EFAE5270C /* Pods-DailyNotificationPlugin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DailyNotificationPlugin.debug.xcconfig"; path = "Target Support Files/Pods-DailyNotificationPlugin/Pods-DailyNotificationPlugin.debug.xcconfig"; sourceTree = "<group>"; };
467AB34F611231718368D768 /* DailyNotificationLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyNotificationLogger.swift; sourceTree = "<group>"; };
6495D32429F76744DC98B457 /* DailyNotificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyNotificationTests.swift; sourceTree = "<group>"; };
77711E259A9C3D73936E2780 /* Pods-DailyNotificationPlugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DailyNotificationPlugin.release.xcconfig"; path = "Target Support Files/Pods-DailyNotificationPlugin/Pods-DailyNotificationPlugin.release.xcconfig"; sourceTree = "<group>"; };
7DA0C384AE2BD3E27E1CA95A /* Pods-DailyNotificationPluginTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DailyNotificationPluginTests.release.xcconfig"; path = "Target Support Files/Pods-DailyNotificationPluginTests/Pods-DailyNotificationPluginTests.release.xcconfig"; sourceTree = "<group>"; };
9237F98BBE39C5667CCCF78C /* DailyNotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyNotificationConstants.swift; sourceTree = "<group>"; };
A645658475F4138A9256D485 /* DailyNotificationPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyNotificationPlugin.swift; sourceTree = "<group>"; };
A73A4B8720F98987381BAECF /* index.ts */ = {isa = PBXFileReference; path = index.ts; sourceTree = "<group>"; };
AA32A2FDCE5869E99D5888F0 /* DailyNotificationPluginTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = DailyNotificationPluginTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DC43315277A65E01BD1B352F /* DailyNotificationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyNotificationError.swift; sourceTree = "<group>"; };
FFC45ABFC1A903AE6233B13F /* DailyNotificationConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyNotificationConfig.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
55585DA18B4D813764BADC93 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
74067B7FB473F9455DABAA30 /* Pods_DailyNotificationPlugin.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8D6E11ADD3F7437A18DDD332 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5898E89B868436827E1E06DF /* DailyNotificationPlugin.framework in Frameworks */,
8640E8860A5334043F24DC54 /* Pods_DailyNotificationPluginTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1E538212868D96F5FE5949D3 /* Plugin */ = {
isa = PBXGroup;
children = (
FFC45ABFC1A903AE6233B13F /* DailyNotificationConfig.swift */,
9237F98BBE39C5667CCCF78C /* DailyNotificationConstants.swift */,
DC43315277A65E01BD1B352F /* DailyNotificationError.swift */,
467AB34F611231718368D768 /* DailyNotificationLogger.swift */,
A645658475F4138A9256D485 /* DailyNotificationPlugin.swift */,
A73A4B8720F98987381BAECF /* index.ts */,
2DDEB96E881144AB9DBCDF17 /* README.md */,
);
path = Plugin;
sourceTree = "<group>";
};
28D6F94971201D3DB74C25C2 = {
isa = PBXGroup;
children = (
1E538212868D96F5FE5949D3 /* Plugin */,
3233C506859453B03BDE86D8 /* Tests */,
E84F19FCBB1C18FE94E42EC8 /* Products */,
FA2E2F2AFEF5A51D9DCAFC04 /* Pods */,
ADB432E27D513A3C69B9A1A3 /* Frameworks */,
);
sourceTree = "<group>";
};
3233C506859453B03BDE86D8 /* Tests */ = {
isa = PBXGroup;
children = (
6495D32429F76744DC98B457 /* DailyNotificationTests.swift */,
);
path = Tests;
sourceTree = "<group>";
};
ADB432E27D513A3C69B9A1A3 /* Frameworks */ = {
isa = PBXGroup;
children = (
3BD2A2F1CA91755E648A5D57 /* Pods_DailyNotificationPlugin.framework */,
0A49F9F065B6559C77DE3BD5 /* Pods_DailyNotificationPluginTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
E84F19FCBB1C18FE94E42EC8 /* Products */ = {
isa = PBXGroup;
children = (
3323D7F1B3ED08FAA559D317 /* DailyNotificationPlugin.framework */,
AA32A2FDCE5869E99D5888F0 /* DailyNotificationPluginTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
FA2E2F2AFEF5A51D9DCAFC04 /* Pods */ = {
isa = PBXGroup;
children = (
4494D62E3E3D3A7EFAE5270C /* Pods-DailyNotificationPlugin.debug.xcconfig */,
77711E259A9C3D73936E2780 /* Pods-DailyNotificationPlugin.release.xcconfig */,
40B0BB9ACA2D2A1BEB4DF9A2 /* Pods-DailyNotificationPluginTests.debug.xcconfig */,
7DA0C384AE2BD3E27E1CA95A /* Pods-DailyNotificationPluginTests.release.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
257C4D3AD8FBFC25B796808A /* DailyNotificationPlugin */ = {
isa = PBXNativeTarget;
buildConfigurationList = A48909A0B23F2E1853CA7243 /* Build configuration list for PBXNativeTarget "DailyNotificationPlugin" */;
buildPhases = (
EFC33670012401F59F542C6C /* [CP] Check Pods Manifest.lock */,
B64C03AB42C5F59F0C2AC34C /* Sources */,
F64E92967F4F9B8AB5FB3FF0 /* Resources */,
55585DA18B4D813764BADC93 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = DailyNotificationPlugin;
productName = DailyNotificationPlugin;
productReference = 3323D7F1B3ED08FAA559D317 /* DailyNotificationPlugin.framework */;
productType = "com.apple.product-type.framework";
};
D5D84A92030AF309D12F0C04 /* DailyNotificationPluginTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 29C4C700B6D1011122DEB3D1 /* Build configuration list for PBXNativeTarget "DailyNotificationPluginTests" */;
buildPhases = (
2A3C79169070A704F233230B /* [CP] Check Pods Manifest.lock */,
55FB7A11B0C278223BAC8576 /* Sources */,
8D6E11ADD3F7437A18DDD332 /* Frameworks */,
4943F65747C3ABB97AEBDDB9 /* Embed Frameworks */,
7B305C495763B32DED093F95 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
E48942294A3D346D124D468C /* PBXTargetDependency */,
);
name = DailyNotificationPluginTests;
productName = DailyNotificationPluginTests;
productReference = AA32A2FDCE5869E99D5888F0 /* DailyNotificationPluginTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
006593AF8D5F74184E8E7C52 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1430;
TargetAttributes = {
257C4D3AD8FBFC25B796808A = {
DevelopmentTeam = "";
};
D5D84A92030AF309D12F0C04 = {
DevelopmentTeam = "";
};
};
};
buildConfigurationList = E3A89DF03E1CDA836997EEC6 /* Build configuration list for PBXProject "DailyNotificationPlugin" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
Base,
en,
);
mainGroup = 28D6F94971201D3DB74C25C2;
productRefGroup = E84F19FCBB1C18FE94E42EC8 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
257C4D3AD8FBFC25B796808A /* DailyNotificationPlugin */,
D5D84A92030AF309D12F0C04 /* DailyNotificationPluginTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
F64E92967F4F9B8AB5FB3FF0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6C1E173CC70849A66F85B12C /* README.md in Resources */,
F86B65B48D5B072F30F76479 /* index.ts in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
2A3C79169070A704F233230B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-DailyNotificationPluginTests-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;
};
7B305C495763B32DED093F95 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-DailyNotificationPluginTests/Pods-DailyNotificationPluginTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-DailyNotificationPluginTests/Pods-DailyNotificationPluginTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DailyNotificationPluginTests/Pods-DailyNotificationPluginTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
EFC33670012401F59F542C6C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-DailyNotificationPlugin-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;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
55FB7A11B0C278223BAC8576 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2B7E978FB6B43664754FC9BB /* DailyNotificationTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B64C03AB42C5F59F0C2AC34C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3C8161B717E367A8B88111BF /* DailyNotificationConfig.swift in Sources */,
FB9C99C0B426E0109ED1218C /* DailyNotificationConstants.swift in Sources */,
92CCC02492ECD5CADABE7BC4 /* DailyNotificationError.swift in Sources */,
DBCD22D6FACC2C730D7C2911 /* DailyNotificationLogger.swift in Sources */,
C194055B816EA1C2DCF17BD2 /* DailyNotificationPlugin.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
E48942294A3D346D124D468C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 257C4D3AD8FBFC25B796808A /* DailyNotificationPlugin */;
targetProxy = AE616C66C793C36141ED183E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
1B945D5C7C74FADDDFCFBE5B /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 77711E259A9C3D73936E2780 /* Pods-DailyNotificationPlugin.release.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.timesafari.dailynotification;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
34E9AA395681C624E34D67AC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4494D62E3E3D3A7EFAE5270C /* Pods-DailyNotificationPlugin.debug.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.timesafari.dailynotification;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
67AF4EA7655D29A052EF8B83 /* 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_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
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;
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 = (
"$(inherited)",
"DEBUG=1",
);
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 = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
8C3734FD07E9594E1FAA5E80 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7DA0C384AE2BD3E27E1CA95A /* Pods-DailyNotificationPluginTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.timesafari.dailynotification.tests;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
9A90FB54CF53D768F76987E3 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 40B0BB9ACA2D2A1BEB4DF9A2 /* Pods-DailyNotificationPluginTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.timesafari.dailynotification.tests;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
E64E663501BF0EF5E09805E2 /* 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_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
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;
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;
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
29C4C700B6D1011122DEB3D1 /* Build configuration list for PBXNativeTarget "DailyNotificationPluginTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9A90FB54CF53D768F76987E3 /* Debug */,
8C3734FD07E9594E1FAA5E80 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
A48909A0B23F2E1853CA7243 /* Build configuration list for PBXNativeTarget "DailyNotificationPlugin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
34E9AA395681C624E34D67AC /* Debug */,
1B945D5C7C74FADDDFCFBE5B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
E3A89DF03E1CDA836997EEC6 /* Build configuration list for PBXProject "DailyNotificationPlugin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
67AF4EA7655D29A052EF8B83 /* Debug */,
E64E663501BF0EF5E09805E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
/* End XCConfigurationList section */
};
rootObject = 006593AF8D5F74184E8E7C52 /* Project object */;
}

7
ios/DailyNotificationPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

103
ios/DailyNotificationPlugin.xcodeproj/xcshareddata/xcschemes/DailyNotificationPlugin.xcscheme

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "257C4D3AD8FBFC25B796808A"
BuildableName = "DailyNotificationPlugin.framework"
BlueprintName = "DailyNotificationPlugin"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
onlyGenerateCoverageForSpecifiedTargets = "NO">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "257C4D3AD8FBFC25B796808A"
BuildableName = "DailyNotificationPlugin.framework"
BlueprintName = "DailyNotificationPlugin"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5D84A92030AF309D12F0C04"
BuildableName = "DailyNotificationPluginTests.xctest"
BlueprintName = "DailyNotificationPluginTests"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<CommandLineArguments>
</CommandLineArguments>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "257C4D3AD8FBFC25B796808A"
BuildableName = "DailyNotificationPlugin.framework"
BlueprintName = "DailyNotificationPlugin"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<CommandLineArguments>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<CommandLineArguments>
</CommandLineArguments>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "257C4D3AD8FBFC25B796808A"
BuildableName = "DailyNotificationPlugin.framework"
BlueprintName = "DailyNotificationPlugin"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

99
ios/DailyNotificationPlugin.xcodeproj/xcshareddata/xcschemes/DailyNotificationPluginTests.xcscheme

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5D84A92030AF309D12F0C04"
BuildableName = "DailyNotificationPluginTests.xctest"
BlueprintName = "DailyNotificationPluginTests"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
onlyGenerateCoverageForSpecifiedTargets = "NO">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5D84A92030AF309D12F0C04"
BuildableName = "DailyNotificationPluginTests.xctest"
BlueprintName = "DailyNotificationPluginTests"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5D84A92030AF309D12F0C04"
BuildableName = "DailyNotificationPluginTests.xctest"
BlueprintName = "DailyNotificationPluginTests"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<CommandLineArguments>
</CommandLineArguments>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5D84A92030AF309D12F0C04"
BuildableName = "DailyNotificationPluginTests.xctest"
BlueprintName = "DailyNotificationPluginTests"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5D84A92030AF309D12F0C04"
BuildableName = "DailyNotificationPluginTests.xctest"
BlueprintName = "DailyNotificationPluginTests"
ReferencedContainer = "container:DailyNotificationPlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

10
ios/DailyNotificationPlugin.xcworkspace/contents.xcworkspacedata

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:DailyNotificationPlugin.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

BIN
ios/DailyNotificationPlugin.xcworkspace/xcuserdata/cloud.xcuserdatad/UserInterfaceState.xcuserstate

Binary file not shown.

31
ios/Plugin/DailyNotificationConfig.swift

@ -0,0 +1,31 @@
/**
* DailyNotificationConfig.swift
* Daily Notification Plugin for Capacitor
*
* Provides configuration options for the notification plugin
*/
import Foundation
/// Configuration options for the DailyNotification plugin
///
/// This singleton structure provides configurable options that can be modified
/// to customize the plugin's behavior.
public struct DailyNotificationConfig {
/// Shared instance for singleton access
public static var shared = DailyNotificationConfig()
/// Maximum number of notifications that can be scheduled per day
public var maxNotificationsPerDay = 10
/// Default timezone for notifications when none is specified
public var defaultTimeZone = TimeZone.current
/// Whether debug logging is enabled
public var loggingEnabled = true
/// Number of days to retain delivered notifications
public var retentionDays = 7
private init() {}
}

52
ios/Plugin/DailyNotificationConstants.swift

@ -0,0 +1,52 @@
/**
* DailyNotificationConstants.swift
* Daily Notification Plugin for Capacitor
*
* Defines constant values used throughout the notification plugin
*/
import Foundation
/// Constants used throughout the DailyNotification plugin
///
/// This structure provides centralized access to all constant values used in the plugin,
/// making it easier to maintain and update common values.
public struct DailyNotificationConstants {
/// Default notification title when none is provided
public static let defaultTitle = "Daily Notification"
/// Default notification body when none is provided
public static let defaultBody = "Your daily update is ready"
/// Prefix used for notification identifiers
public static let notificationIdentifierPrefix = "daily-notification-"
/// Name of the event emitted for notification interactions
public static let eventName = "notification"
/// Default settings for notifications
public struct Settings {
/// Whether sound is enabled by default
public static let defaultSound = true
/// Default priority level for notifications
public static let defaultPriority = "default"
/// Default number of retry attempts
public static let defaultRetryCount = 3
/// Default interval between retries (in milliseconds)
public static let defaultRetryInterval = 1000
}
/// Keys used in plugin method calls
public struct Keys {
public static let url = "url"
public static let time = "time"
public static let title = "title"
public static let body = "body"
public static let sound = "sound"
public static let priority = "priority"
public static let timezone = "timezone"
}
}

50
ios/Plugin/DailyNotificationError.swift

@ -0,0 +1,50 @@
/**
* DailyNotificationError.swift
* Daily Notification Plugin for Capacitor
*
* Defines error types and handling for the notification plugin
*/
import Foundation
/// Represents possible errors that can occur within the DailyNotification plugin
///
/// These errors provide specific failure cases and associated messages for better
/// error handling and debugging in the notification scheduling process.
public enum DailyNotificationError: Error {
/// Thrown when required parameters are missing or invalid
case invalidParameters(String)
/// Thrown when notification permissions have not been granted
case permissionDenied
/// Thrown when notification scheduling fails
case schedulingFailed(String)
/// Thrown when time format is invalid (should be HH:mm)
case invalidTimeFormat
/// Thrown when provided timezone identifier is invalid
case invalidTimezone
/// Thrown when priority value is not one of: high, default, low
case invalidPriority
/// Human-readable error messages for each error case
public var message: String {
switch self {
case .invalidParameters(let detail):
return "Invalid parameters: \(detail)"
case .permissionDenied:
return "Notification permissions not granted"
case .schedulingFailed(let reason):
return "Failed to schedule notification: \(reason)"
case .invalidTimeFormat:
return "Invalid time format. Expected HH:mm"
case .invalidTimezone:
return "Invalid timezone identifier"
case .invalidPriority:
return "Invalid priority value. Expected 'high', 'default', or 'low'"
}
}
}

44
ios/Plugin/DailyNotificationLogger.swift

@ -0,0 +1,44 @@
/**
* DailyNotificationLogger.swift
* Daily Notification Plugin for Capacitor
*
* Provides logging functionality for the notification plugin
*/
import Foundation
/// Logger utility for the DailyNotification plugin
///
/// Provides structured logging capabilities with different severity levels
/// and automatic file/line/function information.
public class DailyNotificationLogger {
/// Shared instance for singleton access
public static let shared = DailyNotificationLogger()
/// Available logging levels
public enum Level: String {
case debug, info, warning, error
}
private init() {}
/// Log a message with the specified severity level
/// - Parameters:
/// - level: The severity level of the log
/// - message: The message to log
/// - file: The file where the log was called (automatic)
/// - function: The function where the log was called (automatic)
/// - line: The line number where the log was called (automatic)
public func log(
_ level: Level,
_ message: String,
file: String = #file,
function: String = #function,
line: Int = #line
) {
#if DEBUG
let fileName = (file as NSString).lastPathComponent
print("[\(level.rawValue.uppercased())] [\(fileName):\(line)] \(function): \(message)")
#endif
}
}

253
ios/Plugin/DailyNotificationPlugin.swift

@ -9,10 +9,29 @@ import Foundation
import Capacitor
import UserNotifications
/// Represents the main plugin class for handling daily notifications
///
/// This plugin provides functionality for scheduling and managing daily notifications
/// on iOS devices using the UserNotifications framework.
@objc(DailyNotificationPlugin)
public class DailyNotificationPlugin: CAPPlugin {
private let notificationCenter = UNUserNotificationCenter.current()
private var settings: [String: Any] = [
"sound": true,
"priority": "default",
"retryCount": 3,
"retryInterval": 1000
]
private static let CHANNEL_ID = "daily_notification_channel"
private static let CHANNEL_NAME = "Daily Notifications"
private static let CHANNEL_DESCRIPTION = "Daily notification updates"
/// Schedules a new daily notification
/// - Parameter call: The plugin call containing notification parameters
/// - Returns: Void
/// - Throws: DailyNotificationError
@objc func scheduleDailyNotification(_ call: CAPPluginCall) {
guard let url = call.getString("url"),
let time = call.getString("time") else {
@ -39,25 +58,51 @@ public class DailyNotificationPlugin: CAPPlugin {
// Set priority
if let priority = call.getString("priority") {
switch priority {
case "high":
content.interruptionLevel = .timeSensitive
case "low":
content.interruptionLevel = .passive
default:
content.interruptionLevel = .active
if #available(iOS 15.0, *) {
switch priority {
case "high":
content.interruptionLevel = .timeSensitive
case "low":
content.interruptionLevel = .passive
default:
content.interruptionLevel = .active
}
}
}
// Add to notification content setup
content.categoryIdentifier = "DAILY_NOTIFICATION"
let category = UNNotificationCategory(
identifier: "DAILY_NOTIFICATION",
actions: [],
intentIdentifiers: [],
options: .customDismissAction
)
notificationCenter.setNotificationCategories([category])
// Create trigger for daily notification
var dateComponents = DateComponents()
dateComponents.hour = hour
dateComponents.minute = minute
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
// Add check for past time and adjust to next day
let calendar = Calendar.current
var components = DateComponents()
components.hour = hour
components.minute = minute
components.second = 0
if let date = calendar.date(from: components),
date.timeIntervalSinceNow <= 0 {
components.day = calendar.component(.day, from: Date()) + 1
}
// Create request
let identifier = String(format: "daily-notification-%d", (url as NSString).hash)
content.userInfo = ["url": url]
let request = UNNotificationRequest(
identifier: "daily-notification-\(url)",
identifier: identifier,
content: content,
trigger: trigger
)
@ -92,18 +137,192 @@ public class DailyNotificationPlugin: CAPPlugin {
}
@objc func getNotificationStatus(_ call: CAPPluginCall) {
notificationCenter.getPendingNotificationRequests { requests in
let nextNotification = requests.first
let result: [String: Any] = [
"nextNotificationTime": nextNotification?.trigger?.nextTriggerDate?.timeIntervalSince1970 ?? 0,
"isEnabled": true // TODO: Check system notification settings
]
call.resolve(result)
notificationCenter.getNotificationSettings { settings in
self.notificationCenter.getPendingNotificationRequests { requests in
var result: [String: Any] = [
"isEnabled": settings.authorizationStatus == .authorized,
"pending": requests.count
]
if let nextRequest = requests.first,
let trigger = nextRequest.trigger as? UNCalendarNotificationTrigger {
result["nextNotificationTime"] = trigger.nextTriggerDate()?.timeIntervalSince1970 ?? 0
}
// Add current settings
result["settings"] = self.settings
call.resolve(result)
}
}
}
@objc func updateSettings(_ call: CAPPluginCall) {
// TODO: Implement settings update
call.resolve()
if let sound = call.getBool("sound") {
settings["sound"] = sound
}
if let priority = call.getString("priority") {
guard ["high", "default", "low"].contains(priority) else {
call.reject("Invalid priority value")
return
}
settings["priority"] = priority
}
if let timezone = call.getString("timezone") {
guard TimeZone(identifier: timezone) != nil else {
call.reject("Invalid timezone")
return
}
settings["timezone"] = timezone
}
// Update any existing notifications with new settings
notificationCenter.getPendingNotificationRequests { [weak self] requests in
guard let self = self else { return }
for request in requests {
let content = request.content.mutableCopy() as! UNMutableNotificationContent
// Update notification content based on new settings
content.sound = self.settings["sound"] as! Bool ? .default : nil
if let priority = self.settings["priority"] as? String {
if #available(iOS 15.0, *) {
switch priority {
case "high": content.interruptionLevel = .timeSensitive
case "low": content.interruptionLevel = .passive
default: content.interruptionLevel = .active
}
}
}
let newRequest = UNNotificationRequest(
identifier: request.identifier,
content: content,
trigger: request.trigger
)
self.notificationCenter.add(newRequest)
}
}
call.resolve(settings)
}
@objc public override func checkPermissions(_ call: CAPPluginCall) {
notificationCenter.getNotificationSettings { settings in
var result: [String: Any] = [:]
// Convert authorization status
switch settings.authorizationStatus {
case .authorized:
result["status"] = "granted"
case .denied:
result["status"] = "denied"
case .provisional:
result["status"] = "provisional"
case .ephemeral:
result["status"] = "ephemeral"
default:
result["status"] = "unknown"
}
// Add detailed settings
result["alert"] = settings.alertSetting == .enabled
result["badge"] = settings.badgeSetting == .enabled
result["sound"] = settings.soundSetting == .enabled
result["lockScreen"] = settings.lockScreenSetting == .enabled
result["carPlay"] = settings.carPlaySetting == .enabled
call.resolve(result)
}
}
@objc public override func requestPermissions(_ call: CAPPluginCall) {
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
notificationCenter.requestAuthorization(options: options) { granted, error in
if let error = error {
call.reject("Failed to request permissions: \(error.localizedDescription)")
return
}
call.resolve([
"granted": granted
])
}
}
public override func load() {
notificationCenter.delegate = self
}
private func isValidTime(_ time: String) -> Bool {
let timeComponents = time.split(separator: ":")
guard timeComponents.count == 2,
let hour = Int(timeComponents[0]),
let minute = Int(timeComponents[1]) else {
return false
}
return hour >= 0 && hour < 24 && minute >= 0 && minute < 60
}
private func isValidTimezone(_ identifier: String) -> Bool {
return TimeZone(identifier: identifier) != nil
}
private func cleanupOldNotifications() {
let cutoffDate = Date().addingTimeInterval(-Double(DailyNotificationConfig.shared.retentionDays * 24 * 60 * 60))
notificationCenter.getDeliveredNotifications { notifications in
let oldNotifications = notifications.filter { $0.date < cutoffDate }
self.notificationCenter.removeDeliveredNotifications(withIdentifiers: oldNotifications.map { $0.request.identifier })
}
}
private func setupNotificationChannel() {
// iOS doesn't use notification channels like Android
// This method is kept for API compatibility
}
}
extension DailyNotificationPlugin: UNUserNotificationCenterDelegate {
public func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let notification = response.notification
let userInfo = notification.request.content.userInfo
// Create notification event data
let eventData: [String: Any] = [
"id": notification.request.identifier,
"title": notification.request.content.title,
"body": notification.request.content.body,
"action": response.actionIdentifier,
"data": userInfo
]
// Notify JavaScript
notifyListeners("notification", data: eventData)
completionHandler()
}
// Handle notifications when app is in foreground
public func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
var presentationOptions: UNNotificationPresentationOptions = []
if #available(iOS 14.0, *) {
presentationOptions = [.banner, .sound, .badge]
} else {
presentationOptions = [.alert, .sound, .badge]
}
completionHandler(presentationOptions)
}
}

19
ios/Podfile

@ -0,0 +1,19 @@
platform :ios, '13.0'
use_frameworks!
source 'https://cdn.cocoapods.org/'
def capacitor_pods
pod 'Capacitor', :path => '../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../node_modules/@capacitor/ios'
end
target 'DailyNotificationPlugin' do
capacitor_pods
pod 'DailyNotificationPlugin', :path => '.'
end
target 'DailyNotificationPluginTests' do
capacitor_pods
pod 'DailyNotificationPlugin', :path => '.'
end

29
ios/Podfile.lock

@ -0,0 +1,29 @@
PODS:
- Capacitor (5.0.0):
- CapacitorCordova
- CapacitorCordova (5.0.0)
- DailyNotificationPlugin (1.0.0):
- Capacitor
- CapacitorCordova
DEPENDENCIES:
- "Capacitor (from `../node_modules/@capacitor/ios`)"
- "CapacitorCordova (from `../node_modules/@capacitor/ios`)"
- DailyNotificationPlugin (from `.`)
EXTERNAL SOURCES:
Capacitor:
:path: "../node_modules/@capacitor/ios"
CapacitorCordova:
:path: "../node_modules/@capacitor/ios"
DailyNotificationPlugin:
:path: "."
SPEC CHECKSUMS:
Capacitor: ba8cd5cce13c6ab3c4faf7ef98487be481c9c1c8
CapacitorCordova: 4ea17670ee562680988a7ce9db68dee5160fe564
DailyNotificationPlugin: 59b7578061086ff48fd72151c36cdbd90f004bf5
PODFILE CHECKSUM: ac8c229d24347f6f83e67e6b95458e0b81e68f7c
COCOAPODS: 1.16.2

29
ios/Tests/DailyNotificationTests.swift

@ -0,0 +1,29 @@
import XCTest
@testable import Plugin
class DailyNotificationTests: XCTestCase {
var plugin: DailyNotificationPlugin!
override func setUp() {
super.setUp()
plugin = DailyNotificationPlugin()
}
func testTimeValidation() {
// Valid time
XCTAssertTrue(plugin.isValidTime("09:00"))
// Invalid times
XCTAssertFalse(plugin.isValidTime("25:00"))
XCTAssertFalse(plugin.isValidTime("09:60"))
XCTAssertFalse(plugin.isValidTime("9:00"))
XCTAssertFalse(plugin.isValidTime("0900"))
}
func testTimezoneValidation() {
XCTAssertTrue(plugin.isValidTimezone("America/New_York"))
XCTAssertFalse(plugin.isValidTimezone("Invalid/Timezone"))
}
// Add more tests...
}

52
ios/project.yml

@ -0,0 +1,52 @@
name: DailyNotificationPlugin
options:
bundleIdPrefix: com.timesafari
deploymentTarget:
iOS: 13.0
schemes:
DailyNotificationPlugin:
build:
targets:
DailyNotificationPlugin: all
run:
config: Debug
test:
targets:
- DailyNotificationPluginTests
config: Debug
profile:
config: Release
analyze:
config: Debug
archive:
config: Release
DailyNotificationPluginTests:
build:
targets:
DailyNotificationPluginTests: all
test:
targets:
- DailyNotificationPluginTests
config: Debug
targets:
DailyNotificationPlugin:
type: framework
platform: iOS
sources:
- path: Plugin
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.timesafari.dailynotification
DEVELOPMENT_TEAM: "" # Add your team ID here
dependencies: []
DailyNotificationPluginTests:
type: bundle.unit-test
platform: iOS
sources:
- path: Tests
dependencies:
- target: DailyNotificationPlugin
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.timesafari.dailynotification.tests
DEVELOPMENT_TEAM: "" # Add your team ID here

12
package-lock.json

@ -11,7 +11,8 @@
"license": "MIT",
"dependencies": {
"@capacitor/android": "^5.0.0",
"@capacitor/core": "^5.0.0"
"@capacitor/core": "^5.0.0",
"@capacitor/ios": "^5.0.0"
},
"devDependencies": {
"@capacitor/cli": "^5.0.0",
@ -702,6 +703,15 @@
"tslib": "^2.1.0"
}
},
"node_modules/@capacitor/ios": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-5.0.0.tgz",
"integrity": "sha512-b1edQNe1cKiqnxoIR5WxbVjDlf3RWr2ZjaDxwEuBzwBAvvrFcweKdbw1ij45DWHKODaIymWoyAlAUN+vFOF5sw==",
"license": "MIT",
"peerDependencies": {
"@capacitor/core": "^5.0.0"
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz",

3
package.json

@ -29,7 +29,8 @@
"license": "MIT",
"dependencies": {
"@capacitor/android": "^5.0.0",
"@capacitor/core": "^5.0.0"
"@capacitor/core": "^5.0.0",
"@capacitor/ios": "^5.0.0"
},
"devDependencies": {
"@capacitor/cli": "^5.0.0",

Loading…
Cancel
Save