ios-2 #2
12
package-lock.json
generated
12
package-lock.json
generated
@@ -100,6 +100,7 @@
|
||||
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
@@ -649,6 +650,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.1.tgz",
|
||||
"integrity": "sha512-urZwxa7hVE/BnA18oCFAdizXPse6fCKanQyEqpmz6cBJ2vObwMpyJDG5jBeoSsgocS9+Ax+9vb4ducWJn0y2qQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -751,6 +753,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@@ -774,6 +777,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -2925,6 +2929,7 @@
|
||||
"integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.62.0",
|
||||
"@typescript-eslint/types": "5.62.0",
|
||||
@@ -3128,6 +3133,7 @@
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -3543,6 +3549,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001688",
|
||||
"electron-to-chromium": "^1.5.73",
|
||||
@@ -4692,6 +4699,7 @@
|
||||
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
@@ -6249,6 +6257,7 @@
|
||||
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^29.7.0",
|
||||
"@jest/types": "^29.6.3",
|
||||
@@ -7115,6 +7124,7 @@
|
||||
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cssstyle": "^4.2.1",
|
||||
"data-urls": "^5.0.0",
|
||||
@@ -9574,6 +9584,7 @@
|
||||
"integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
@@ -10526,6 +10537,7 @@
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
||||
@@ -31,20 +31,57 @@ npm install
|
||||
|
||||
**Note**: The `postinstall` script automatically fixes Capacitor configuration files after installation.
|
||||
|
||||
### Capacitor Sync (Android)
|
||||
## Building for Android and iOS
|
||||
|
||||
### Quick Build (Recommended)
|
||||
|
||||
Use the unified build script for both platforms:
|
||||
|
||||
```bash
|
||||
# Build and run both platforms on emulator/simulator
|
||||
./scripts/build.sh --run
|
||||
|
||||
# Build both platforms (no run)
|
||||
./scripts/build.sh
|
||||
|
||||
# Build Android only
|
||||
./scripts/build.sh --android
|
||||
|
||||
# Build iOS only
|
||||
./scripts/build.sh --ios
|
||||
|
||||
# Build and run Android on emulator
|
||||
./scripts/build.sh --run-android
|
||||
|
||||
# Build and run iOS on simulator
|
||||
./scripts/build.sh --run-ios
|
||||
```
|
||||
|
||||
**See**: `docs/BUILD_QUICK_REFERENCE.md` for detailed build instructions.
|
||||
|
||||
### Manual Build Steps
|
||||
|
||||
#### Capacitor Sync
|
||||
|
||||
**Important**: Use the wrapper script instead of `npx cap sync` directly to automatically fix plugin paths:
|
||||
|
||||
```sh
|
||||
# Sync both platforms
|
||||
npm run cap:sync
|
||||
|
||||
# Sync Android only
|
||||
npm run cap:sync:android
|
||||
|
||||
# Sync iOS only
|
||||
npm run cap:sync:ios
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Run `npx cap sync android`
|
||||
1. Run `npx cap sync` (or platform-specific sync)
|
||||
2. Automatically fix `capacitor.settings.gradle` (corrects plugin path from `android/` to `android/plugin/`)
|
||||
3. Ensure `capacitor.plugins.json` has the correct plugin registration
|
||||
|
||||
If you run `npx cap sync android` directly, you can manually fix afterward:
|
||||
If you run `npx cap sync` directly, you can manually fix afterward:
|
||||
```sh
|
||||
node scripts/fix-capacitor-plugins.js
|
||||
```
|
||||
|
||||
@@ -2,47 +2,194 @@
|
||||
|
||||
**Author**: Matthew Raymer
|
||||
**Date**: October 17, 2025
|
||||
**Last Updated**: November 19, 2025
|
||||
|
||||
## ⚡ Quick Start
|
||||
|
||||
**Easiest way to build and run:**
|
||||
|
||||
```bash
|
||||
# Build and run both platforms
|
||||
./scripts/build.sh --run
|
||||
|
||||
# Or build only
|
||||
./scripts/build.sh
|
||||
```
|
||||
|
||||
This script handles everything automatically! See [Unified Build Script](#-unified-build-script-recommended) section for all options.
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Critical Build Steps
|
||||
|
||||
### Prerequisites
|
||||
|
||||
**Required for All Platforms:**
|
||||
- Node.js 20.19.0+ or 22.12.0+
|
||||
- npm (comes with Node.js)
|
||||
- Plugin must be built (`npm run build` in plugin root directory)
|
||||
- The build script will automatically build the plugin if `dist/` doesn't exist
|
||||
|
||||
**For Android:**
|
||||
- Java JDK 22.12 or later
|
||||
- Android SDK (with `adb` in PATH)
|
||||
- Gradle (comes with Android project)
|
||||
|
||||
**For iOS:**
|
||||
- macOS with Xcode (xcodebuild must be in PATH)
|
||||
- CocoaPods (`pod --version` to check)
|
||||
- Can be installed via rbenv (script handles this automatically)
|
||||
- iOS deployment target: iOS 13.0+
|
||||
|
||||
**Plugin Requirements:**
|
||||
- Plugin podspec must exist at: `node_modules/@timesafari/daily-notification-plugin/ios/DailyNotificationPlugin.podspec`
|
||||
- Plugin must be installed: `npm install` (uses `file:../../` reference)
|
||||
- Plugin must be built: `npm run build` in plugin root (creates `dist/` directory)
|
||||
|
||||
### Initial Setup (One-Time)
|
||||
|
||||
```bash
|
||||
# 1. Build web assets
|
||||
# 1. Install dependencies (includes @capacitor/ios)
|
||||
npm install
|
||||
|
||||
# 2. Add iOS platform (if not already added)
|
||||
npx cap add ios
|
||||
|
||||
# 3. Install iOS dependencies
|
||||
cd ios/App
|
||||
pod install
|
||||
cd ../..
|
||||
```
|
||||
|
||||
### Build for Both Platforms
|
||||
|
||||
```bash
|
||||
# 1. Build web assets (required for both platforms)
|
||||
npm run build
|
||||
|
||||
# 2. Sync with native projects (automatically fixes plugin paths)
|
||||
# 2. Sync with native projects (syncs both Android and iOS)
|
||||
npm run cap:sync
|
||||
|
||||
# 3. Build and deploy Android
|
||||
# OR sync platforms individually:
|
||||
# npm run cap:sync:android # Android only
|
||||
# npm run cap:sync:ios # iOS only
|
||||
```
|
||||
|
||||
### Android Build
|
||||
|
||||
```bash
|
||||
# Build Android APK
|
||||
cd android
|
||||
./gradlew :app:assembleDebug
|
||||
|
||||
# Install on device/emulator
|
||||
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||||
|
||||
# Launch app
|
||||
adb shell am start -n com.timesafari.dailynotification.test/.MainActivity
|
||||
```
|
||||
|
||||
### iOS Build
|
||||
|
||||
```bash
|
||||
# Open in Xcode
|
||||
cd ios/App
|
||||
open App.xcworkspace
|
||||
|
||||
# Or build from command line
|
||||
xcodebuild -workspace App.xcworkspace \
|
||||
-scheme App \
|
||||
-configuration Debug \
|
||||
-sdk iphonesimulator \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 15' \
|
||||
build
|
||||
|
||||
# Or use Capacitor CLI
|
||||
npx cap run ios
|
||||
```
|
||||
|
||||
## ⚠️ Why `npm run cap:sync` is Important
|
||||
|
||||
**Problem**: `npx cap sync` overwrites `capacitor.plugins.json` and `capacitor.settings.gradle` with incorrect paths.
|
||||
|
||||
**Solution**: The `cap:sync` script automatically:
|
||||
1. Runs `npx cap sync android`
|
||||
1. Runs `npx cap sync` (syncs both Android and iOS)
|
||||
2. Fixes `capacitor.settings.gradle` (corrects plugin path from `android/` to `android/plugin/`)
|
||||
3. Restores the DailyNotification plugin entry in `capacitor.plugins.json`
|
||||
|
||||
**Platform-specific sync:**
|
||||
- `npm run cap:sync:android` - Syncs Android only (includes fix script)
|
||||
- `npm run cap:sync:ios` - Syncs iOS only (no fix needed for iOS)
|
||||
|
||||
**Without the fix**: Plugin detection fails, build errors occur, "simplified dialog" appears.
|
||||
|
||||
## 🔍 Verification Checklist
|
||||
|
||||
After build, verify:
|
||||
### Android Verification
|
||||
|
||||
- [ ] `capacitor.plugins.json` contains DailyNotification entry
|
||||
After Android build, verify:
|
||||
|
||||
- [ ] `android/app/src/main/assets/capacitor.plugins.json` contains DailyNotification entry
|
||||
- [ ] System Status shows "Plugin: Available" (green)
|
||||
- [ ] Plugin Diagnostics shows all 4 plugins
|
||||
- [ ] Click events work on ActionCard components
|
||||
- [ ] No "simplified dialog" appears
|
||||
|
||||
## 🛠️ Automated Build Script
|
||||
### iOS Verification
|
||||
|
||||
Create `scripts/build-and-deploy.sh`:
|
||||
After iOS build, verify:
|
||||
|
||||
- [ ] iOS project exists at `ios/App/App.xcworkspace`
|
||||
- [ ] CocoaPods installed (`pod install` completed successfully)
|
||||
- [ ] Plugin framework linked in Xcode project
|
||||
- [ ] App builds without errors in Xcode
|
||||
- [ ] Plugin methods accessible from JavaScript
|
||||
- [ ] System Status shows "Plugin: Available" (green)
|
||||
|
||||
## 🛠️ Automated Build Scripts
|
||||
|
||||
### Unified Build Script (Recommended)
|
||||
|
||||
The project includes a comprehensive build script that handles both platforms:
|
||||
|
||||
```bash
|
||||
# Build both platforms
|
||||
./scripts/build.sh
|
||||
|
||||
# Build Android only
|
||||
./scripts/build.sh --android
|
||||
|
||||
# Build iOS only
|
||||
./scripts/build.sh --ios
|
||||
|
||||
# Build and run Android on emulator
|
||||
./scripts/build.sh --run-android
|
||||
|
||||
# Build and run iOS on simulator
|
||||
./scripts/build.sh --run-ios
|
||||
|
||||
# Build and run both platforms
|
||||
./scripts/build.sh --run
|
||||
|
||||
# Show help
|
||||
./scripts/build.sh --help
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- ✅ Automatically builds web assets
|
||||
- ✅ Syncs Capacitor with both platforms
|
||||
- ✅ Builds Android APK
|
||||
- ✅ Builds iOS app for simulator
|
||||
- ✅ Automatically finds and uses available emulator/simulator
|
||||
- ✅ Installs and launches apps when using `--run` flags
|
||||
- ✅ Color-coded output for easy reading
|
||||
- ✅ Comprehensive error handling
|
||||
|
||||
### Manual Build Scripts
|
||||
|
||||
#### Build for Android
|
||||
|
||||
Create `scripts/build-android.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
@@ -52,7 +199,7 @@ echo "🔨 Building web assets..."
|
||||
npm run build
|
||||
|
||||
echo "🔄 Syncing with native projects..."
|
||||
npm run cap:sync
|
||||
npm run cap:sync:android
|
||||
# This automatically syncs and fixes plugin paths
|
||||
|
||||
echo "🏗️ Building Android app..."
|
||||
@@ -63,7 +210,64 @@ echo "📱 Installing and launching..."
|
||||
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||||
adb shell am start -n com.timesafari.dailynotification.test/.MainActivity
|
||||
|
||||
echo "✅ Build and deploy complete!"
|
||||
echo "✅ Android build and deploy complete!"
|
||||
```
|
||||
|
||||
### Build for iOS
|
||||
|
||||
Create `scripts/build-ios.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🔨 Building web assets..."
|
||||
npm run build
|
||||
|
||||
echo "🔄 Syncing with iOS..."
|
||||
npm run cap:sync:ios
|
||||
|
||||
echo "🍎 Building iOS app..."
|
||||
cd ios/App
|
||||
pod install
|
||||
xcodebuild -workspace App.xcworkspace \
|
||||
-scheme App \
|
||||
-configuration Debug \
|
||||
-sdk iphonesimulator \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 15' \
|
||||
build
|
||||
|
||||
echo "✅ iOS build complete!"
|
||||
echo "📱 Open Xcode to run on simulator: open App.xcworkspace"
|
||||
```
|
||||
|
||||
### Build for Both Platforms
|
||||
|
||||
Create `scripts/build-all.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🔨 Building web assets..."
|
||||
npm run build
|
||||
|
||||
echo "🔄 Syncing with all native projects..."
|
||||
npm run cap:sync
|
||||
|
||||
echo "🏗️ Building Android..."
|
||||
cd android && ./gradlew :app:assembleDebug && cd ..
|
||||
|
||||
echo "🍎 Building iOS..."
|
||||
cd ios/App && pod install && cd ../..
|
||||
xcodebuild -workspace ios/App/App.xcworkspace \
|
||||
-scheme App \
|
||||
-configuration Debug \
|
||||
-sdk iphonesimulator \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 15' \
|
||||
build
|
||||
|
||||
echo "✅ All platforms built successfully!"
|
||||
```
|
||||
|
||||
## 🐛 Common Issues
|
||||
@@ -74,9 +278,15 @@ echo "✅ Build and deploy complete!"
|
||||
| Plugin not detected | "Plugin: Not Available" (red) | Check plugin registry, rebuild |
|
||||
| Click events not working | Buttons don't respond | Check Vue 3 compatibility, router config |
|
||||
| Inconsistent status | Different status in different cards | Use consistent detection logic |
|
||||
| **No podspec found** | `[!] No podspec found for 'TimesafariDailyNotificationPlugin'` | Run `node scripts/fix-capacitor-plugins.js` to fix Podfile, then `pod install` |
|
||||
| **Plugin not built** | Vite build fails: "Failed to resolve entry" | Run `npm run build` in plugin root directory (`../../`) |
|
||||
| **CocoaPods not found** | `pod: command not found` | Install CocoaPods: `sudo gem install cocoapods` or via rbenv |
|
||||
| **Xcode not found** | `xcodebuild: command not found` | Install Xcode from App Store, run `xcode-select --install` |
|
||||
|
||||
## 📱 Testing Commands
|
||||
|
||||
### Android Testing
|
||||
|
||||
```bash
|
||||
# Check plugin registry
|
||||
cat android/app/src/main/assets/capacitor.plugins.json
|
||||
@@ -86,8 +296,38 @@ adb logcat | grep -i "dailynotification\|capacitor\|plugin"
|
||||
|
||||
# Check app installation
|
||||
adb shell pm list packages | grep dailynotification
|
||||
|
||||
# View app logs
|
||||
adb logcat -s DailyNotification
|
||||
```
|
||||
|
||||
### iOS Testing
|
||||
|
||||
```bash
|
||||
# Check if iOS project exists
|
||||
ls -la ios/App/App.xcworkspace
|
||||
|
||||
# Check CocoaPods installation
|
||||
cd ios/App && pod install && cd ../..
|
||||
|
||||
# Monitor iOS logs (simulator)
|
||||
xcrun simctl spawn booted log stream | grep -i "dailynotification\|capacitor\|plugin"
|
||||
|
||||
# Check plugin in Xcode
|
||||
# Open ios/App/App.xcworkspace in Xcode
|
||||
# Check: Project Navigator → Frameworks → DailyNotificationPlugin.framework
|
||||
|
||||
# View device logs (physical device)
|
||||
# Xcode → Window → Devices and Simulators → Select device → Open Console
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Remember**: Use `npm run cap:sync` instead of `npx cap sync android` directly - it automatically fixes the configuration files!
|
||||
## 📝 Important Notes
|
||||
|
||||
**Remember**:
|
||||
- Use `npm run cap:sync` to sync both platforms (automatically fixes Android configuration files)
|
||||
- Use `npm run cap:sync:android` for Android-only sync (includes fix script)
|
||||
- Use `npm run cap:sync:ios` for iOS-only sync
|
||||
- Always run `npm run build` before syncing to ensure latest web assets are copied
|
||||
- For iOS: Run `pod install` in `ios/App/` after first sync or when dependencies change
|
||||
|
||||
13
test-apps/daily-notification-test/ios/.gitignore
vendored
Normal file
13
test-apps/daily-notification-test/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
|
||||
@@ -0,0 +1,408 @@
|
||||
// !$*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;
|
||||
packageReferences = (
|
||||
);
|
||||
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 */;
|
||||
}
|
||||
10
test-apps/daily-notification-test/ios/App/App.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
test-apps/daily-notification-test/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>
|
||||
@@ -0,0 +1,49 @@
|
||||
import UIKit
|
||||
import Capacitor
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// 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/daily-notification-test/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
vendored
Normal file
23
test-apps/daily-notification-test/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/daily-notification-test/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
vendored
Normal file
BIN
test-apps/daily-notification-test/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/daily-notification-test/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
vendored
Normal file
BIN
test-apps/daily-notification-test/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/daily-notification-test/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
vendored
Normal file
BIN
test-apps/daily-notification-test/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>
|
||||
62
test-apps/daily-notification-test/ios/App/App/Info.plist
Normal file
62
test-apps/daily-notification-test/ios/App/App/Info.plist
Normal file
@@ -0,0 +1,62 @@
|
||||
<?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>Daily Notification Test</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/>
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.timesafari.dailynotification.fetch</string>
|
||||
<string>com.timesafari.dailynotification.notify</string>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>background-fetch</string>
|
||||
<string>background-processing</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>NSUserNotificationsUsageDescription</key>
|
||||
<string>This app uses notifications to deliver daily updates and reminders.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
24
test-apps/daily-notification-test/ios/App/Podfile
Normal file
24
test-apps/daily-notification-test/ios/App/Podfile
Normal file
@@ -0,0 +1,24 @@
|
||||
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'
|
||||
pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios'
|
||||
end
|
||||
|
||||
target 'App' do
|
||||
capacitor_pods
|
||||
# Add your Pods here
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
assertDeploymentTarget(installer)
|
||||
end
|
||||
@@ -45,7 +45,7 @@
|
||||
},
|
||||
"../..": {
|
||||
"name": "@timesafari/daily-notification-plugin",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.11",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build",
|
||||
"lint": "eslint . --fix",
|
||||
"cap:sync": "npx cap sync android && node scripts/fix-capacitor-plugins.js",
|
||||
"cap:sync": "npx cap sync && node scripts/fix-capacitor-plugins.js",
|
||||
"cap:sync:android": "npx cap sync android && node scripts/fix-capacitor-plugins.js",
|
||||
"cap:sync:ios": "npx cap sync ios",
|
||||
"postinstall": "node scripts/fix-capacitor-plugins.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^6.2.1",
|
||||
"@capacitor/ios": "^6.2.1",
|
||||
"@capacitor/cli": "^6.2.1",
|
||||
"@capacitor/core": "^6.2.1",
|
||||
"@timesafari/daily-notification-plugin": "file:../../",
|
||||
|
||||
569
test-apps/daily-notification-test/scripts/build.sh
Executable file
569
test-apps/daily-notification-test/scripts/build.sh
Executable file
@@ -0,0 +1,569 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build script for daily-notification-test Capacitor app
|
||||
# Supports both Android and iOS with emulator/simulator deployment
|
||||
#
|
||||
# Requirements:
|
||||
# - Node.js 20.19.0+ or 22.12.0+
|
||||
# - npm
|
||||
# - Plugin must be built (script will auto-build if needed)
|
||||
# - For Android: Java JDK 22.12+, Android SDK (adb)
|
||||
# - For iOS: Xcode, CocoaPods (pod)
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/build.sh # Build both platforms
|
||||
# ./scripts/build.sh --android # Build Android only
|
||||
# ./scripts/build.sh --ios # Build iOS only
|
||||
# ./scripts/build.sh --run # Build and run both
|
||||
# ./scripts/build.sh --help # Show help
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# Logging functions
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
# Validation functions
|
||||
check_command() {
|
||||
if ! command -v $1 &> /dev/null; then
|
||||
log_error "$1 is not installed. Please install it first."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get pod command (handles rbenv)
|
||||
get_pod_command() {
|
||||
if command -v pod &> /dev/null; then
|
||||
echo "pod"
|
||||
elif [ -f "$HOME/.rbenv/shims/pod" ]; then
|
||||
echo "$HOME/.rbenv/shims/pod"
|
||||
else
|
||||
log_error "CocoaPods (pod) not found. Please install CocoaPods first."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check requirements
|
||||
check_requirements() {
|
||||
log_step "Checking build requirements..."
|
||||
|
||||
local missing_requirements=false
|
||||
|
||||
# Check Node.js
|
||||
if ! command -v node &> /dev/null; then
|
||||
log_error "Node.js is not installed. Please install Node.js 20.19.0+ or 22.12.0+"
|
||||
missing_requirements=true
|
||||
else
|
||||
log_info "✅ Node.js: $(node --version)"
|
||||
fi
|
||||
|
||||
# Check npm
|
||||
if ! command -v npm &> /dev/null; then
|
||||
log_error "npm is not installed"
|
||||
missing_requirements=true
|
||||
else
|
||||
log_info "✅ npm: $(npm --version)"
|
||||
fi
|
||||
|
||||
# Check plugin is built
|
||||
PLUGIN_ROOT="$(cd "$PROJECT_DIR/../.." && pwd)"
|
||||
if [ ! -d "$PLUGIN_ROOT/dist" ]; then
|
||||
log_warn "Plugin not built. Building plugin now..."
|
||||
cd "$PLUGIN_ROOT"
|
||||
if npm run build; then
|
||||
log_info "✅ Plugin built successfully"
|
||||
else
|
||||
log_error "Failed to build plugin. Please run 'npm run build' in the plugin root directory."
|
||||
missing_requirements=true
|
||||
fi
|
||||
cd "$PROJECT_DIR"
|
||||
else
|
||||
log_info "✅ Plugin built (dist/ exists)"
|
||||
fi
|
||||
|
||||
# Check Android requirements if building Android
|
||||
if [ "$BUILD_ALL" = true ] || [ "$BUILD_ANDROID" = true ]; then
|
||||
if ! command -v adb &> /dev/null; then
|
||||
log_warn "Android SDK not found (adb not in PATH). Android build will be skipped."
|
||||
else
|
||||
log_info "✅ Android SDK: $(adb version | head -1)"
|
||||
fi
|
||||
|
||||
if ! command -v java &> /dev/null; then
|
||||
log_warn "Java not found. Android build may fail."
|
||||
else
|
||||
log_info "✅ Java: $(java -version 2>&1 | head -1)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check iOS requirements if building iOS
|
||||
if [ "$BUILD_ALL" = true ] || [ "$BUILD_IOS" = true ]; then
|
||||
if ! command -v xcodebuild &> /dev/null; then
|
||||
log_warn "Xcode not found (xcodebuild not in PATH). iOS build will be skipped."
|
||||
else
|
||||
log_info "✅ Xcode: $(xcodebuild -version | head -1)"
|
||||
fi
|
||||
|
||||
POD_CMD=$(get_pod_command 2>/dev/null || echo "")
|
||||
if [ -z "$POD_CMD" ]; then
|
||||
log_warn "CocoaPods not found. iOS build will be skipped."
|
||||
else
|
||||
log_info "✅ CocoaPods: $($POD_CMD --version 2>/dev/null || echo 'found')"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$missing_requirements" = true ]; then
|
||||
log_error "Missing required dependencies. Please install them and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "All requirements satisfied"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
BUILD_ANDROID=false
|
||||
BUILD_IOS=false
|
||||
BUILD_ALL=true
|
||||
RUN_ANDROID=false
|
||||
RUN_IOS=false
|
||||
RUN_ALL=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--android)
|
||||
BUILD_ANDROID=true
|
||||
BUILD_ALL=false
|
||||
shift
|
||||
;;
|
||||
--ios)
|
||||
BUILD_IOS=true
|
||||
BUILD_ALL=false
|
||||
shift
|
||||
;;
|
||||
--run-android)
|
||||
RUN_ANDROID=true
|
||||
BUILD_ANDROID=true
|
||||
BUILD_ALL=false
|
||||
shift
|
||||
;;
|
||||
--run-ios)
|
||||
RUN_IOS=true
|
||||
BUILD_IOS=true
|
||||
BUILD_ALL=false
|
||||
shift
|
||||
;;
|
||||
--run)
|
||||
RUN_ALL=true
|
||||
BUILD_ALL=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --android Build Android only"
|
||||
echo " --ios Build iOS only"
|
||||
echo " --run-android Build and run Android on emulator"
|
||||
echo " --run-ios Build and run iOS on simulator"
|
||||
echo " --run Build and run both platforms"
|
||||
echo " --help, -h Show this help message"
|
||||
echo ""
|
||||
echo "Default: Build both platforms (no run)"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown option: $1"
|
||||
echo "Use --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Change to project directory
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
log_info "Building daily-notification-test app"
|
||||
log_info "Project directory: $PROJECT_DIR"
|
||||
|
||||
# Check requirements
|
||||
check_requirements
|
||||
|
||||
# Step 1: Build web assets
|
||||
log_step "Building web assets..."
|
||||
if ! npm run build; then
|
||||
log_error "Web build failed"
|
||||
exit 1
|
||||
fi
|
||||
log_info "Web assets built successfully"
|
||||
|
||||
# Step 2: Sync Capacitor
|
||||
log_step "Syncing Capacitor with native projects..."
|
||||
if ! npm run cap:sync; then
|
||||
log_error "Capacitor sync failed"
|
||||
exit 1
|
||||
fi
|
||||
log_info "Capacitor sync completed"
|
||||
|
||||
# Step 2.5: Ensure fix script ran (it should have via cap:sync, but verify for iOS)
|
||||
if [ "$BUILD_ALL" = true ] || [ "$BUILD_IOS" = true ]; then
|
||||
if [ -d "$PROJECT_DIR/ios" ]; then
|
||||
log_step "Verifying iOS Podfile configuration..."
|
||||
if node "$PROJECT_DIR/scripts/fix-capacitor-plugins.js" 2>/dev/null; then
|
||||
log_info "iOS Podfile verified"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Android build
|
||||
if [ "$BUILD_ALL" = true ] || [ "$BUILD_ANDROID" = true ]; then
|
||||
log_step "Building Android app..."
|
||||
|
||||
# Check for Android SDK
|
||||
if ! command -v adb &> /dev/null; then
|
||||
log_warn "adb not found. Android SDK may not be installed."
|
||||
log_warn "Skipping Android build. Install Android SDK to build Android."
|
||||
else
|
||||
cd "$PROJECT_DIR/android"
|
||||
|
||||
# Build APK
|
||||
if ./gradlew :app:assembleDebug; then
|
||||
log_info "Android APK built successfully"
|
||||
|
||||
APK_PATH="$PROJECT_DIR/android/app/build/outputs/apk/debug/app-debug.apk"
|
||||
|
||||
if [ -f "$APK_PATH" ]; then
|
||||
log_info "APK location: $APK_PATH"
|
||||
|
||||
# Run on emulator if requested
|
||||
if [ "$RUN_ALL" = true ] || [ "$RUN_ANDROID" = true ]; then
|
||||
log_step "Installing and launching Android app..."
|
||||
|
||||
# Check for running emulator
|
||||
if ! adb devices | grep -q "device$"; then
|
||||
log_warn "No Android emulator/device found"
|
||||
log_info "Please start an Android emulator and try again"
|
||||
log_info "Or use: adb devices to check connected devices"
|
||||
else
|
||||
# Install APK
|
||||
if adb install -r "$APK_PATH"; then
|
||||
log_info "APK installed successfully"
|
||||
|
||||
# Launch app
|
||||
if adb shell am start -n com.timesafari.dailynotification.test/.MainActivity; then
|
||||
log_info "✅ Android app launched successfully!"
|
||||
else
|
||||
log_warn "Failed to launch app (may already be running)"
|
||||
fi
|
||||
else
|
||||
log_warn "APK installation failed (may already be installed)"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_error "APK not found at expected location: $APK_PATH"
|
||||
fi
|
||||
else
|
||||
log_error "Android build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
# iOS build
|
||||
if [ "$BUILD_ALL" = true ] || [ "$BUILD_IOS" = true ]; then
|
||||
log_step "Building iOS app..."
|
||||
|
||||
# Check for Xcode
|
||||
if ! command -v xcodebuild &> /dev/null; then
|
||||
log_warn "xcodebuild not found. Xcode may not be installed."
|
||||
log_warn "Skipping iOS build. Install Xcode to build iOS."
|
||||
else
|
||||
IOS_DIR="$PROJECT_DIR/ios/App"
|
||||
|
||||
if [ ! -d "$IOS_DIR" ]; then
|
||||
log_warn "iOS directory not found. Adding iOS platform..."
|
||||
cd "$PROJECT_DIR"
|
||||
npx cap add ios
|
||||
fi
|
||||
|
||||
cd "$IOS_DIR"
|
||||
|
||||
# Install CocoaPods dependencies
|
||||
log_step "Installing CocoaPods dependencies..."
|
||||
POD_CMD=$(get_pod_command)
|
||||
|
||||
# Check if Podfile exists and has correct plugin reference
|
||||
if [ -f "$IOS_DIR/Podfile" ]; then
|
||||
# Run fix script to ensure Podfile is correct
|
||||
log_step "Verifying Podfile configuration..."
|
||||
if node "$PROJECT_DIR/scripts/fix-capacitor-plugins.js" 2>/dev/null; then
|
||||
log_info "Podfile verified"
|
||||
fi
|
||||
fi
|
||||
|
||||
if $POD_CMD install; then
|
||||
log_info "CocoaPods dependencies installed"
|
||||
else
|
||||
log_error "CocoaPods install failed"
|
||||
log_info "Troubleshooting:"
|
||||
log_info "1. Check that plugin podspec exists: ls -la $PLUGIN_ROOT/ios/DailyNotificationPlugin.podspec"
|
||||
log_info "2. Verify Podfile references: pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios'"
|
||||
log_info "3. Run fix script: node scripts/fix-capacitor-plugins.js"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find workspace
|
||||
WORKSPACE="$IOS_DIR/App.xcworkspace"
|
||||
if [ ! -d "$WORKSPACE" ]; then
|
||||
WORKSPACE="$IOS_DIR/App.xcodeproj"
|
||||
fi
|
||||
|
||||
if [ ! -d "$WORKSPACE" ]; then
|
||||
log_error "Xcode workspace/project not found at $IOS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get simulator
|
||||
log_step "Finding available iOS simulator..."
|
||||
|
||||
# Method 1: Use xcodebuild to get available destinations (most reliable)
|
||||
# This gives us the exact format xcodebuild expects
|
||||
DESTINATION_STRING=$(xcodebuild -workspace "$WORKSPACE" -scheme App -showdestinations 2>/dev/null | \
|
||||
grep "iOS Simulator" | \
|
||||
grep -i "iphone" | \
|
||||
grep -v "iPhone Air" | \
|
||||
head -1)
|
||||
|
||||
if [ -n "$DESTINATION_STRING" ]; then
|
||||
# Extract name from destination string
|
||||
# Format: "platform=iOS Simulator,id=...,name=iPhone 17 Pro,OS=26.0.1"
|
||||
SIMULATOR=$(echo "$DESTINATION_STRING" | \
|
||||
sed -n 's/.*name=\([^,]*\).*/\1/p' | \
|
||||
sed 's/[[:space:]]*$//')
|
||||
log_info "Found simulator via xcodebuild: $SIMULATOR"
|
||||
fi
|
||||
|
||||
# Method 2: Fallback to simctl if xcodebuild didn't work
|
||||
if [ -z "$SIMULATOR" ] || [ "$SIMULATOR" = "Shutdown" ] || [ "$SIMULATOR" = "Booted" ]; then
|
||||
# Use simctl list in JSON format for more reliable parsing
|
||||
# This avoids parsing status words like "Shutdown"
|
||||
SIMULATOR_JSON=$(xcrun simctl list devices available --json 2>/dev/null)
|
||||
|
||||
if [ -n "$SIMULATOR_JSON" ]; then
|
||||
# Extract first iPhone device name using jq if available, or grep/sed
|
||||
if command -v jq &> /dev/null; then
|
||||
SIMULATOR=$(echo "$SIMULATOR_JSON" | \
|
||||
jq -r '.devices | to_entries[] | .value[] | select(.name | test("iPhone"; "i")) | .name' | \
|
||||
grep -v "iPhone Air" | \
|
||||
head -1)
|
||||
else
|
||||
# Fallback: parse text output more carefully
|
||||
# Get line with iPhone, extract name before first parenthesis
|
||||
SIMULATOR_LINE=$(xcrun simctl list devices available 2>/dev/null | \
|
||||
grep -E "iPhone [0-9]" | \
|
||||
grep -v "iPhone Air" | \
|
||||
head -1)
|
||||
|
||||
if [ -n "$SIMULATOR_LINE" ]; then
|
||||
# Extract device name - everything before first "("
|
||||
SIMULATOR=$(echo "$SIMULATOR_LINE" | \
|
||||
sed -E 's/^[[:space:]]*([^(]+).*/\1/' | \
|
||||
sed 's/[[:space:]]*$//')
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate it's not a status word
|
||||
if [ "$SIMULATOR" = "Shutdown" ] || [ "$SIMULATOR" = "Booted" ] || [ "$SIMULATOR" = "Creating" ] || [ -z "$SIMULATOR" ]; then
|
||||
SIMULATOR=""
|
||||
else
|
||||
log_info "Found simulator via simctl: $SIMULATOR"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Method 3: Try to find iPhone 17 Pro specifically (preferred)
|
||||
if [ -z "$SIMULATOR" ] || [ "$SIMULATOR" = "Shutdown" ] || [ "$SIMULATOR" = "Booted" ]; then
|
||||
PRO_LINE=$(xcrun simctl list devices available 2>/dev/null | \
|
||||
grep -i "iPhone 17 Pro" | \
|
||||
head -1)
|
||||
|
||||
if [ -n "$PRO_LINE" ]; then
|
||||
PRO_SIM=$(echo "$PRO_LINE" | \
|
||||
awk -F'(' '{print $1}' | \
|
||||
sed 's/^[[:space:]]*//' | \
|
||||
sed 's/[[:space:]]*$//')
|
||||
|
||||
if [ -n "$PRO_SIM" ] && [ "$PRO_SIM" != "Shutdown" ] && [ "$PRO_SIM" != "Booted" ] && [ "$PRO_SIM" != "Creating" ]; then
|
||||
SIMULATOR="$PRO_SIM"
|
||||
log_info "Using preferred simulator: $SIMULATOR"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Final fallback to known good simulator
|
||||
if [ -z "$SIMULATOR" ] || [ "$SIMULATOR" = "Shutdown" ] || [ "$SIMULATOR" = "Booted" ] || [ "$SIMULATOR" = "Creating" ]; then
|
||||
# Try common simulator names that are likely to exist
|
||||
for DEFAULT_SIM in "iPhone 17 Pro" "iPhone 17" "iPhone 16" "iPhone 15 Pro" "iPhone 15"; do
|
||||
if xcrun simctl list devices available 2>/dev/null | grep -q "$DEFAULT_SIM"; then
|
||||
SIMULATOR="$DEFAULT_SIM"
|
||||
log_info "Using fallback simulator: $SIMULATOR"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# If still empty, use iPhone 17 Pro as final default
|
||||
if [ -z "$SIMULATOR" ] || [ "$SIMULATOR" = "Shutdown" ] || [ "$SIMULATOR" = "Booted" ]; then
|
||||
log_warn "Could not determine simulator. Using default: iPhone 17 Pro"
|
||||
SIMULATOR="iPhone 17 Pro"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "Selected simulator: $SIMULATOR"
|
||||
|
||||
# Extract device ID for more reliable targeting
|
||||
# Format: " iPhone 17 Pro (68D19D08-4701-422C-AF61-2E21ACA1DD4C) (Shutdown)"
|
||||
SIMULATOR_ID=$(xcrun simctl list devices available 2>/dev/null | \
|
||||
grep -i "$SIMULATOR" | \
|
||||
head -1 | \
|
||||
sed -n 's/.*(\([A-F0-9-]\{36\}\)).*/\1/p')
|
||||
|
||||
# Verify simulator exists before building
|
||||
if [ -z "$SIMULATOR_ID" ] && ! xcrun simctl list devices available 2>/dev/null | grep -q "$SIMULATOR"; then
|
||||
log_warn "Simulator '$SIMULATOR' not found in available devices"
|
||||
log_info "Available iPhone simulators:"
|
||||
xcrun simctl list devices available 2>/dev/null | grep -i "iphone" | grep -v "iPhone Air" | head -5
|
||||
log_warn "Attempting build anyway with: $SIMULATOR"
|
||||
fi
|
||||
|
||||
# Build iOS app
|
||||
log_step "Building iOS app for simulator..."
|
||||
|
||||
# Use device ID if available, otherwise use name
|
||||
if [ -n "$SIMULATOR_ID" ]; then
|
||||
DESTINATION="platform=iOS Simulator,id=$SIMULATOR_ID"
|
||||
log_info "Using simulator ID: $SIMULATOR_ID ($SIMULATOR)"
|
||||
else
|
||||
DESTINATION="platform=iOS Simulator,name=$SIMULATOR"
|
||||
log_info "Using simulator name: $SIMULATOR"
|
||||
fi
|
||||
|
||||
if xcodebuild -workspace "$WORKSPACE" \
|
||||
-scheme App \
|
||||
-configuration Debug \
|
||||
-sdk iphonesimulator \
|
||||
-destination "$DESTINATION" \
|
||||
build; then
|
||||
log_info "iOS app built successfully"
|
||||
|
||||
# Find built app
|
||||
DERIVED_DATA="$HOME/Library/Developer/Xcode/DerivedData"
|
||||
APP_PATH=$(find "$DERIVED_DATA" -name "App.app" -path "*/Build/Products/Debug-iphonesimulator/*" -type d 2>/dev/null | head -1)
|
||||
|
||||
if [ -n "$APP_PATH" ]; then
|
||||
log_info "App built at: $APP_PATH"
|
||||
|
||||
# Run on simulator if requested
|
||||
if [ "$RUN_ALL" = true ] || [ "$RUN_IOS" = true ]; then
|
||||
log_step "Installing and launching iOS app on simulator..."
|
||||
|
||||
# Use the device ID we already extracted, or get it again
|
||||
if [ -z "$SIMULATOR_ID" ]; then
|
||||
SIMULATOR_ID=$(xcrun simctl list devices available 2>/dev/null | \
|
||||
grep -i "$SIMULATOR" | \
|
||||
head -1 | \
|
||||
sed -n 's/.*(\([A-F0-9-]\{36\}\)).*/\1/p')
|
||||
fi
|
||||
|
||||
# If we have device ID, use it; otherwise try to boot by name
|
||||
if [ -n "$SIMULATOR_ID" ]; then
|
||||
SIMULATOR_UDID="$SIMULATOR_ID"
|
||||
log_info "Using simulator ID: $SIMULATOR_UDID"
|
||||
else
|
||||
# Try to boot simulator by name and get its ID
|
||||
log_step "Booting simulator: $SIMULATOR..."
|
||||
xcrun simctl boot "$SIMULATOR" 2>/dev/null || true
|
||||
sleep 2
|
||||
SIMULATOR_UDID=$(xcrun simctl list devices 2>/dev/null | \
|
||||
grep -i "$SIMULATOR" | \
|
||||
grep -E "\([A-F0-9-]{36}\)" | \
|
||||
head -1 | \
|
||||
sed -n 's/.*(\([A-F0-9-]\{36\}\)).*/\1/p')
|
||||
fi
|
||||
|
||||
if [ -n "$SIMULATOR_UDID" ]; then
|
||||
# Install app
|
||||
if xcrun simctl install "$SIMULATOR_UDID" "$APP_PATH"; then
|
||||
log_info "App installed on simulator"
|
||||
|
||||
# Launch app
|
||||
APP_BUNDLE_ID="com.timesafari.dailynotification.test"
|
||||
if xcrun simctl launch "$SIMULATOR_UDID" "$APP_BUNDLE_ID"; then
|
||||
log_info "✅ iOS app launched successfully!"
|
||||
else
|
||||
log_warn "Failed to launch app (may already be running)"
|
||||
fi
|
||||
else
|
||||
log_warn "App installation failed (may already be installed)"
|
||||
fi
|
||||
else
|
||||
log_warn "Could not find or boot simulator"
|
||||
log_info "Open Xcode and run manually: open $WORKSPACE"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_warn "Could not find built app in DerivedData"
|
||||
log_info "Build succeeded. Open Xcode to run: open $WORKSPACE"
|
||||
fi
|
||||
else
|
||||
log_error "iOS build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info ""
|
||||
log_info "✅ Build process complete!"
|
||||
log_info ""
|
||||
|
||||
# Summary
|
||||
if [ "$BUILD_ANDROID" = true ] || [ "$BUILD_ALL" = true ]; then
|
||||
if [ -f "$PROJECT_DIR/android/app/build/outputs/apk/debug/app-debug.apk" ]; then
|
||||
log_info "Android APK: $PROJECT_DIR/android/app/build/outputs/apk/debug/app-debug.apk"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$BUILD_IOS" = true ] || [ "$BUILD_ALL" = true ]; then
|
||||
if [ -d "$IOS_DIR/App.xcworkspace" ]; then
|
||||
log_info "iOS Workspace: $IOS_DIR/App.xcworkspace"
|
||||
log_info "Open with: open $IOS_DIR/App.xcworkspace"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -22,6 +22,7 @@ const __dirname = path.dirname(__filename);
|
||||
|
||||
const PLUGINS_JSON_PATH = path.join(__dirname, '../android/app/src/main/assets/capacitor.plugins.json');
|
||||
const SETTINGS_GRADLE_PATH = path.join(__dirname, '../android/capacitor.settings.gradle');
|
||||
const PODFILE_PATH = path.join(__dirname, '../ios/App/Podfile');
|
||||
|
||||
const PLUGIN_ENTRY = {
|
||||
name: "DailyNotification",
|
||||
@@ -103,6 +104,98 @@ ${correctPath}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix iOS Podfile to use correct plugin pod name and path
|
||||
*/
|
||||
function fixPodfile() {
|
||||
console.log('🔧 Verifying iOS Podfile...');
|
||||
|
||||
if (!fs.existsSync(PODFILE_PATH)) {
|
||||
console.log('ℹ️ Podfile not found (iOS platform may not be added yet)');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let content = fs.readFileSync(PODFILE_PATH, 'utf8');
|
||||
const originalContent = content;
|
||||
|
||||
// The correct pod reference should be:
|
||||
// pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios'
|
||||
const correctPodLine = "pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios'";
|
||||
|
||||
// Check if Podfile already has the correct reference
|
||||
if (content.includes("pod 'DailyNotificationPlugin'")) {
|
||||
// Check if path is correct
|
||||
if (content.includes('@timesafari/daily-notification-plugin/ios')) {
|
||||
console.log('✅ Podfile has correct DailyNotificationPlugin reference');
|
||||
} else {
|
||||
// Fix the path
|
||||
console.log('⚠️ Podfile has DailyNotificationPlugin but wrong path - fixing...');
|
||||
content = content.replace(
|
||||
/pod ['"]DailyNotificationPlugin['"].*:path.*/,
|
||||
correctPodLine
|
||||
);
|
||||
|
||||
// Also fix if it's using the wrong name (TimesafariDailyNotificationPlugin)
|
||||
content = content.replace(
|
||||
/pod ['"]TimesafariDailyNotificationPlugin['"].*:path.*/,
|
||||
correctPodLine
|
||||
);
|
||||
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(PODFILE_PATH, content);
|
||||
console.log('✅ Fixed DailyNotificationPlugin path in Podfile');
|
||||
}
|
||||
}
|
||||
} else if (content.includes("TimesafariDailyNotificationPlugin")) {
|
||||
// Fix wrong pod name
|
||||
console.log('⚠️ Podfile uses wrong pod name (TimesafariDailyNotificationPlugin) - fixing...');
|
||||
content = content.replace(
|
||||
/pod ['"]TimesafariDailyNotificationPlugin['"].*:path.*/,
|
||||
correctPodLine
|
||||
);
|
||||
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(PODFILE_PATH, content);
|
||||
console.log('✅ Fixed pod name in Podfile (TimesafariDailyNotificationPlugin -> DailyNotificationPlugin)');
|
||||
}
|
||||
} else {
|
||||
// Add the pod reference if it's missing
|
||||
console.log('⚠️ Podfile missing DailyNotificationPlugin - adding...');
|
||||
|
||||
// Find the capacitor_pods function or target section
|
||||
if (content.includes('def capacitor_pods')) {
|
||||
// Add after capacitor_pods function
|
||||
content = content.replace(
|
||||
/(def capacitor_pods[\s\S]*?end)/,
|
||||
`$1\n\n # Daily Notification Plugin\n ${correctPodLine}`
|
||||
);
|
||||
} else if (content.includes("target 'App'")) {
|
||||
// Add in target section
|
||||
content = content.replace(
|
||||
/(target 'App' do)/,
|
||||
`$1\n ${correctPodLine}`
|
||||
);
|
||||
} else {
|
||||
// Add at end before post_install
|
||||
content = content.replace(
|
||||
/(post_install)/,
|
||||
`${correctPodLine}\n\n$1`
|
||||
);
|
||||
}
|
||||
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(PODFILE_PATH, content);
|
||||
console.log('✅ Added DailyNotificationPlugin to Podfile');
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error fixing Podfile:', error.message);
|
||||
// Don't exit - iOS might not be set up yet
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all fixes
|
||||
*/
|
||||
@@ -112,9 +205,10 @@ function fixAll() {
|
||||
|
||||
fixCapacitorPlugins();
|
||||
fixCapacitorSettingsGradle();
|
||||
fixPodfile();
|
||||
|
||||
console.log('\n✅ All fixes applied successfully!');
|
||||
console.log('💡 These fixes will persist until the next "npx cap sync android"');
|
||||
console.log('💡 These fixes will persist until the next "npx cap sync"');
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
@@ -122,4 +216,4 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
fixAll();
|
||||
}
|
||||
|
||||
export { fixCapacitorPlugins, fixCapacitorSettingsGradle, fixAll };
|
||||
export { fixCapacitorPlugins, fixCapacitorSettingsGradle, fixPodfile, fixAll };
|
||||
|
||||
@@ -72,15 +72,20 @@ export class TypedDailyNotificationPlugin implements DailyNotificationBridge {
|
||||
|
||||
/**
|
||||
* Check permissions with validation
|
||||
* Uses checkPermissionStatus() which is the correct method name for iOS
|
||||
*/
|
||||
async checkPermissions(): Promise<PermissionStatus> {
|
||||
try {
|
||||
const result = await (this.plugin as { checkPermissions: () => Promise<PermissionStatus> }).checkPermissions()
|
||||
// Use checkPermissionStatus() which is implemented on both iOS and Android
|
||||
const result = await (this.plugin as { checkPermissionStatus: () => Promise<any> }).checkPermissionStatus()
|
||||
|
||||
// Ensure response has required fields
|
||||
// Map PermissionStatusResult to PermissionStatus format
|
||||
return {
|
||||
notifications: result.notifications || 'denied',
|
||||
notificationsEnabled: Boolean(result.notificationsEnabled)
|
||||
notifications: result.notificationsEnabled ? 'granted' : 'denied',
|
||||
notificationsEnabled: Boolean(result.notificationsEnabled),
|
||||
exactAlarmEnabled: Boolean(result.exactAlarmEnabled),
|
||||
wakeLockEnabled: Boolean(result.wakeLockEnabled),
|
||||
allPermissionsGranted: Boolean(result.allPermissionsGranted)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@@ -166,6 +171,26 @@ export class TypedDailyNotificationPlugin implements DailyNotificationBridge {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request notification permissions (iOS method name)
|
||||
* This is an alias for requestPermissions() for iOS compatibility
|
||||
*/
|
||||
async requestNotificationPermissions(): Promise<void> {
|
||||
try {
|
||||
// Try requestNotificationPermissions first (iOS), fallback to requestPermissions
|
||||
if (typeof (this.plugin as any).requestNotificationPermissions === 'function') {
|
||||
await (this.plugin as { requestNotificationPermissions: () => Promise<void> }).requestNotificationPermissions()
|
||||
} else if (typeof (this.plugin as any).requestPermissions === 'function') {
|
||||
await (this.plugin as { requestPermissions: () => Promise<PermissionStatus> }).requestPermissions()
|
||||
} else {
|
||||
throw new Error('Neither requestNotificationPermissions nor requestPermissions is available')
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error, 'requestNotificationPermissions')
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open exact alarm settings
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,13 @@
|
||||
@click="checkSystemStatus"
|
||||
:loading="isCheckingStatus"
|
||||
/>
|
||||
<ActionCard
|
||||
icon="🔐"
|
||||
title="Request Permissions"
|
||||
description="Check and request notification permissions"
|
||||
@click="checkAndRequestPermissions"
|
||||
:loading="isRequestingPermissions"
|
||||
/>
|
||||
<ActionCard
|
||||
icon="🔔"
|
||||
title="View Notifications"
|
||||
@@ -218,7 +225,8 @@ const checkSystemStatus = async (): Promise<void> => {
|
||||
console.log('✅ Plugin available, checking status...')
|
||||
try {
|
||||
const status = await plugin.getNotificationStatus()
|
||||
const permissions = await plugin.checkPermissions()
|
||||
// Use checkPermissionStatus() which is the correct method name for iOS
|
||||
const permissions = await plugin.checkPermissionStatus()
|
||||
const exactAlarmStatus = await plugin.getExactAlarmStatus()
|
||||
|
||||
console.log('📊 Plugin status object:', status)
|
||||
@@ -232,17 +240,17 @@ const checkSystemStatus = async (): Promise<void> => {
|
||||
|
||||
console.log('📊 Plugin permissions:', permissions)
|
||||
console.log('📊 Permissions details:')
|
||||
console.log(' - notifications:', permissions.notifications)
|
||||
console.log(' - notificationsEnabled:', (permissions as unknown as Record<string, unknown>).notificationsEnabled)
|
||||
console.log(' - exactAlarmEnabled:', (permissions as unknown as Record<string, unknown>).exactAlarmEnabled)
|
||||
console.log(' - wakeLockEnabled:', (permissions as unknown as Record<string, unknown>).wakeLockEnabled)
|
||||
console.log(' - allPermissionsGranted:', (permissions as unknown as Record<string, unknown>).allPermissionsGranted)
|
||||
console.log(' - notificationsEnabled:', permissions.notificationsEnabled)
|
||||
console.log(' - exactAlarmEnabled:', permissions.exactAlarmEnabled)
|
||||
console.log(' - wakeLockEnabled:', permissions.wakeLockEnabled)
|
||||
console.log(' - allPermissionsGranted:', permissions.allPermissionsGranted)
|
||||
console.log('📊 Exact alarm status:', exactAlarmStatus)
|
||||
|
||||
// Map plugin response to app store format
|
||||
// checkPermissionStatus() returns PermissionStatusResult with boolean flags
|
||||
const mappedStatus = {
|
||||
canScheduleNow: status.isEnabled ?? false,
|
||||
postNotificationsGranted: permissions.notifications === 'granted',
|
||||
postNotificationsGranted: permissions.notificationsEnabled ?? false,
|
||||
channelEnabled: true, // Default for now
|
||||
channelImportance: 3, // Default for now
|
||||
channelId: 'daily-notifications',
|
||||
@@ -351,6 +359,80 @@ const refreshSystemStatus = async (): Promise<void> => {
|
||||
await checkSystemStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
* Check permissions and request if needed (Android pattern)
|
||||
* 1. Check permission status first
|
||||
* 2. If not granted, show system dialog
|
||||
* 3. Refresh status after request
|
||||
*/
|
||||
const checkAndRequestPermissions = async (): Promise<void> => {
|
||||
console.log('🔐 CLICK: Check and Request Permissions')
|
||||
|
||||
if (isRequestingPermissions.value) {
|
||||
console.log('⏳ Permission request already in progress')
|
||||
return
|
||||
}
|
||||
|
||||
isRequestingPermissions.value = true
|
||||
|
||||
try {
|
||||
const { DailyNotification } = await import('@timesafari/daily-notification-plugin')
|
||||
const plugin = DailyNotification
|
||||
|
||||
if (!plugin) {
|
||||
console.error('❌ DailyNotification plugin not available')
|
||||
return
|
||||
}
|
||||
|
||||
// Step 1: Check permission status first (Android pattern)
|
||||
console.log('🔍 Step 1: Checking current permission status...')
|
||||
const permissionStatus = await plugin.checkPermissionStatus()
|
||||
|
||||
console.log('📊 Permission status:', {
|
||||
notificationsEnabled: permissionStatus.notificationsEnabled,
|
||||
exactAlarmEnabled: permissionStatus.exactAlarmEnabled,
|
||||
allPermissionsGranted: permissionStatus.allPermissionsGranted
|
||||
})
|
||||
|
||||
// Step 2: If not granted, show system dialog
|
||||
if (!permissionStatus.notificationsEnabled) {
|
||||
console.log('⚠️ Permissions not granted - showing system dialog...')
|
||||
console.log('📱 iOS will show native permission dialog now...')
|
||||
|
||||
// Request permissions - this will show the iOS system dialog
|
||||
// Try requestNotificationPermissions first (iOS), fallback to requestPermissions
|
||||
if (typeof (plugin as any).requestNotificationPermissions === 'function') {
|
||||
await (plugin as { requestNotificationPermissions: () => Promise<void> }).requestNotificationPermissions()
|
||||
} else if (typeof (plugin as any).requestPermissions === 'function') {
|
||||
await (plugin as { requestPermissions: () => Promise<any> }).requestPermissions()
|
||||
} else {
|
||||
throw new Error('Permission request method not available')
|
||||
}
|
||||
|
||||
console.log('✅ Permission request completed')
|
||||
|
||||
// Step 3: Refresh status after request
|
||||
console.log('🔄 Refreshing status after permission request...')
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)) // Wait 1 second for system to update
|
||||
await checkSystemStatus()
|
||||
} else {
|
||||
console.log('✅ Permissions already granted - no dialog needed')
|
||||
// Still refresh status to show current state
|
||||
await checkSystemStatus()
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Permission check/request failed:', error)
|
||||
console.error('❌ Error details:', {
|
||||
name: (error as Error).name,
|
||||
message: (error as Error).message,
|
||||
stack: (error as Error).stack
|
||||
})
|
||||
} finally {
|
||||
isRequestingPermissions.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const runPluginDiagnostics = async (): Promise<void> => {
|
||||
console.log('🔄 CLICK: Plugin Diagnostics - METHOD CALLED!')
|
||||
console.log('🔄 FUNCTION START: runPluginDiagnostics called at', new Date().toISOString())
|
||||
|
||||
@@ -92,7 +92,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
// Test if class can be cast to CapacitorPlugin.Type
|
||||
if let pluginType = aClass as? CAPPlugin.Type {
|
||||
// Try casting to CapacitorPlugin (which is CAPPlugin & CAPBridgedPlugin)
|
||||
if let capacitorPluginType = pluginType as? (CAPPlugin & CAPBridgedPlugin).Type {
|
||||
if pluginType is (CAPPlugin & CAPBridgedPlugin).Type {
|
||||
NSLog("DNP-DEBUG: ✅ Can cast to (CAPPlugin & CAPBridgedPlugin).Type")
|
||||
} else {
|
||||
NSLog("DNP-DEBUG: ❌ Cannot cast to (CAPPlugin & CAPBridgedPlugin).Type")
|
||||
|
||||
Reference in New Issue
Block a user