Browse Source

fix(test-app): resolve plugin detection and remove unused HomeViewSimple

- Fix System Status card to show correct plugin availability
- Add automatic status check on component mount
- Remove HomeViewSimple.vue (no longer needed)
- Fix Vue 3 compatibility issues (@click.native removal)
- Add comprehensive plugin diagnostics with all available plugins
- Implement post-sync script to maintain capacitor.plugins.json
- Add annotation processor for automatic plugin discovery

The DailyNotification plugin now loads correctly and both System Status
and Plugin Diagnostics show consistent, accurate information.
master
Matthew Raymer 4 days ago
parent
commit
200f85a1fb
  1. 4
      test-apps/daily-notification-test/android/app/build.gradle
  2. 14
      test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java
  3. 3
      test-apps/daily-notification-test/android/dailynotification/build.gradle
  4. 58
      test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js
  5. 8
      test-apps/daily-notification-test/src/components/cards/ActionCard.vue
  6. 4
      test-apps/daily-notification-test/src/router/index.ts
  7. 90
      test-apps/daily-notification-test/src/views/HomeView.vue
  8. 258
      test-apps/daily-notification-test/src/views/HomeViewSimple.vue

4
test-apps/daily-notification-test/android/app/build.gradle

@ -40,6 +40,10 @@ dependencies {
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
implementation project(':capacitor-android')
// Capacitor annotation processor for automatic plugin discovery
annotationProcessor project(':capacitor-android')
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"

14
test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java

@ -1,24 +1,10 @@
package com.timesafari.dailynotification.test;
import com.getcapacitor.BridgeActivity;
import com.timesafari.dailynotification.DailyNotificationPlugin;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(android.os.Bundle savedInstanceState) {
android.util.Log.d("MainActivity", "MainActivity.onCreate() called - START");
// Register the DailyNotification plugin BEFORE calling super.onCreate()
android.util.Log.d("MainActivity", "Registering DailyNotification plugin...");
try {
registerPlugin(DailyNotificationPlugin.class);
android.util.Log.d("MainActivity", "DailyNotification plugin registered successfully");
} catch (Exception e) {
android.util.Log.e("MainActivity", "Failed to register DailyNotification plugin", e);
}
super.onCreate(savedInstanceState);
android.util.Log.d("MainActivity", "MainActivity.onCreate() - after super.onCreate()");
android.util.Log.d("MainActivity", "MainActivity.onCreate() called - END");
}
}

3
test-apps/daily-notification-test/android/dailynotification/build.gradle

@ -19,4 +19,7 @@ android {
dependencies {
implementation project(':capacitor-android')
// Capacitor annotation processor for automatic plugin discovery
annotationProcessor project(':capacitor-android')
}

58
test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js

@ -0,0 +1,58 @@
#!/usr/bin/env node
/**
* Post-sync script to fix capacitor.plugins.json
* This ensures the DailyNotification plugin is always registered
* even after npx cap sync overwrites the file
*
* @author Matthew Raymer
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const PLUGINS_JSON_PATH = path.join(__dirname, '../android/app/src/main/assets/capacitor.plugins.json');
const PLUGIN_ENTRY = {
name: "DailyNotification",
classpath: "com.timesafari.dailynotification.DailyNotificationPlugin"
};
function fixCapacitorPlugins() {
console.log('🔧 Fixing capacitor.plugins.json...');
try {
// Read current content
let plugins = [];
if (fs.existsSync(PLUGINS_JSON_PATH)) {
const content = fs.readFileSync(PLUGINS_JSON_PATH, 'utf8');
plugins = JSON.parse(content);
}
// Check if our plugin is already there
const hasPlugin = plugins.some(p => p.name === PLUGIN_ENTRY.name);
if (!hasPlugin) {
plugins.push(PLUGIN_ENTRY);
fs.writeFileSync(PLUGINS_JSON_PATH, JSON.stringify(plugins, null, 2));
console.log('✅ Added DailyNotification plugin to capacitor.plugins.json');
} else {
console.log('✅ DailyNotification plugin already exists in capacitor.plugins.json');
}
} catch (error) {
console.error('❌ Error fixing capacitor.plugins.json:', error.message);
process.exit(1);
}
}
// Run if called directly
if (import.meta.url === `file://${process.argv[1]}`) {
fixCapacitorPlugins();
}
export { fixCapacitorPlugins };

8
test-apps/daily-notification-test/src/components/cards/ActionCard.vue

@ -36,7 +36,13 @@ class ActionCard extends Vue {
@Prop({ type: Boolean, default: false }) loading!: boolean
handleClick() {
if (!this.loading) this.$emit('click')
console.log('🔄 ActionCard handleClick called for:', this.title)
if (!this.loading) {
console.log('🔄 ActionCard emitting click event for:', this.title)
this.$emit('click')
} else {
console.log('🔄 ActionCard click ignored - loading state')
}
}
}

4
test-apps/daily-notification-test/src/router/index.ts

@ -1,5 +1,5 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeViewSimple from '../views/HomeViewSimple.vue'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@ -7,7 +7,7 @@ const router = createRouter({
{
path: '/',
name: 'Home',
component: HomeViewSimple,
component: HomeView,
meta: {
title: 'Daily Notification Test',
requiresAuth: false

90
test-apps/daily-notification-test/src/views/HomeView.vue

@ -100,7 +100,7 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { computed, ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useAppStore } from '@/stores/app'
import ActionCard from '@/components/cards/ActionCard.vue'
@ -178,12 +178,49 @@ const navigateToSettings = (): void => {
const checkSystemStatus = async (): Promise<void> => {
console.log('🔄 CLICK: Check System Status')
isCheckingStatus.value = true
try {
// This will be handled by the app store
console.log('🔧 Checking notification status...')
// For now, just log that we're checking
console.log('🔧 Status check completed (placeholder)')
} finally {
try {
console.log('🔧 Checking system status...')
// Use the same detection logic as runPluginDiagnostics
const { Capacitor } = await import('@capacitor/core')
const platform = Capacitor.getPlatform()
const isNative = platform !== 'web'
if (isNative) {
console.log('🔧 Native platform detected, checking plugin availability...')
// Check if DailyNotification plugin is available
const plugin = (window as any).Capacitor?.Plugins?.DailyNotification
console.log('🔧 DailyNotification plugin check:', plugin ? 'Available' : 'Not Available')
if (plugin) {
console.log('✅ Plugin available, checking status...')
try {
const status = await plugin.checkStatus()
console.log('📊 Plugin status:', status)
// Update the app store status
appStore.setNotificationStatus(status)
console.log('✅ System status updated successfully')
} catch (error) {
console.error('❌ Plugin status check failed:', error)
// Keep existing status or set error state
}
} else {
console.warn('⚠️ DailyNotification plugin not available')
// Reset to error state
appStore.setNotificationStatus(null)
}
} else {
console.log('🌐 Web platform - plugin not available')
appStore.setNotificationStatus(null)
}
console.log('🔧 System status check completed')
} catch (error) {
console.error('❌ System status check failed:', error)
} finally {
isCheckingStatus.value = false
}
}
@ -195,6 +232,7 @@ const refreshSystemStatus = async (): Promise<void> => {
const runPluginDiagnostics = async (): Promise<void> => {
console.log('🔄 CLICK: Plugin Diagnostics - METHOD CALLED!')
console.log('🔄 FUNCTION START: runPluginDiagnostics called at', new Date().toISOString())
try {
console.log('🔧 Running plugin diagnostics...')
console.log('🔧 BUTTON CLICKED - METHOD CALLED!')
@ -221,18 +259,44 @@ const runPluginDiagnostics = async (): Promise<void> => {
if (plugin) {
console.log('✅ DailyNotification plugin available')
// Get all available plugins
const allPlugins = Object.keys((window as any).Capacitor?.Plugins || {})
console.log('📋 All available plugins:', allPlugins)
// Test the checkStatus method
try {
const status = await plugin.checkStatus()
console.log('📊 Plugin status check result:', status)
alert(`✅ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus: ${JSON.stringify(status, null, 2)}`)
// Create detailed plugin report
const pluginReport = {
platform: platform,
nativePlatform: isNative,
dailyNotificationAvailable: true,
allAvailablePlugins: allPlugins,
dailyNotificationStatus: status,
capacitorVersion: (window as any).Capacitor?.getPlatform ? 'Available' : 'Unknown',
webViewInfo: {
userAgent: navigator.userAgent,
platform: navigator.platform
}
}
alert(`✅ Plugin Diagnostics Complete!\n\n` +
`Platform: ${platform}\n` +
`Native Platform: ${isNative}\n` +
`DailyNotification Plugin: Available\n` +
`All Plugins (${allPlugins.length}): ${allPlugins.join(', ')}\n\n` +
`DailyNotification Status:\n${JSON.stringify(status, null, 2)}\n\n` +
`Full Report:\n${JSON.stringify(pluginReport, null, 2)}`)
} catch (error) {
console.error('❌ Plugin status check failed:', error)
alert(`⚠️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus Check Failed: ${error}`)
alert(`⚠️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus Check Failed: ${error}\n\nAll Available Plugins: ${allPlugins.join(', ')}`)
}
} else {
console.warn('⚠️ DailyNotification plugin not available')
alert(`❌ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: No\nAvailable Plugins: ${Object.keys((window as any).Capacitor?.Plugins || {}).join(', ')}`)
const allPlugins = Object.keys((window as any).Capacitor?.Plugins || {})
alert(`❌ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nDailyNotification Plugin: Not Available\n\nAll Available Plugins (${allPlugins.length}):\n${allPlugins.join(', ')}\n\nCapacitor Plugins Object:\n${JSON.stringify((window as any).Capacitor?.Plugins || {}, null, 2)}`)
}
} else {
console.log('🌐 Running in web mode - plugin not available')
@ -249,6 +313,12 @@ const openConsole = (): void => {
console.log('📖 Console opened - check browser developer tools for detailed logs')
alert('📖 Console Logs\n\nOpen your browser\'s Developer Tools (F12) and check the Console tab for detailed diagnostic information.')
}
// Initialize system status when component mounts
onMounted(async () => {
console.log('🏠 HomeView mounted - checking initial system status...')
await checkSystemStatus()
})
</script>
<style scoped>

258
test-apps/daily-notification-test/src/views/HomeViewSimple.vue

@ -1,258 +0,0 @@
<!--
/**
* Simple Home View - Minimal Performance Version
*
* Simplified version to avoid main thread blocking
*
* @author Matthew Raymer
* @version 1.0.0
*/
-->
<template>
<div class="home-view">
<!-- Welcome Section -->
<div class="welcome-section">
<h1 class="welcome-title">
🔔 Daily Notification Test
</h1>
<p class="welcome-subtitle">
Vue 3 + vue-facing-decorator + Capacitor
</p>
<div class="platform-info">
<span class="platform-badge">
{{ platformName }}
</span>
<span class="status-badge">
{{ statusText }}
</span>
</div>
</div>
<!-- Simple Actions -->
<div class="quick-actions">
<h2 class="section-title">Quick Actions</h2>
<div class="action-grid">
<div class="action-card" @click="navigateToSchedule">
<div class="card-content">
<div class="card-icon">📅</div>
<div class="card-text">
<h3 class="card-title">Schedule Notification</h3>
<p class="card-description">Schedule a new daily notification</p>
</div>
<div class="card-arrow"></div>
</div>
</div>
<div class="action-card" @click="checkSystemStatus">
<div class="card-content">
<div class="card-icon">📊</div>
<div class="card-text">
<h3 class="card-title">Check Status</h3>
<p class="card-description">View notification system status</p>
</div>
<div class="card-arrow"></div>
</div>
</div>
<div class="action-card" @click="runPluginDiagnostics">
<div class="card-content">
<div class="card-icon">🔧</div>
<div class="card-text">
<h3 class="card-title">Plugin Diagnostics</h3>
<p class="card-description">Test plugin functionality</p>
</div>
<div class="card-arrow"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, toNative } from 'vue-facing-decorator'
@Component
class HomeViewSimple extends Vue {
platformName = 'Android'
statusText = 'Ready'
navigateToSchedule() {}
checkSystemStatus() { alert('System status check - simplified version') }
runPluginDiagnostics() { alert('Plugin diagnostics - simplified version') }
}
export default toNative(HomeViewSimple)
</script>
<style scoped>
.home-view {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.welcome-section {
text-align: center;
margin-bottom: 40px;
padding: 40px 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 16px;
backdrop-filter: blur(10px);
}
.welcome-title {
margin: 0 0 16px 0;
font-size: 32px;
font-weight: 700;
color: white;
}
.welcome-subtitle {
margin: 0 0 24px 0;
font-size: 18px;
color: rgba(255, 255, 255, 0.8);
}
.platform-info {
display: flex;
justify-content: center;
gap: 16px;
flex-wrap: wrap;
}
.platform-badge, .status-badge {
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.platform-badge {
background: rgba(76, 175, 80, 0.2);
color: #4caf50;
border: 1px solid rgba(76, 175, 80, 0.3);
}
.status-badge {
background: rgba(33, 150, 243, 0.2);
color: #2196f3;
border: 1px solid rgba(33, 150, 243, 0.3);
}
.quick-actions {
margin-bottom: 40px;
}
.section-title {
margin: 0 0 24px 0;
font-size: 24px;
font-weight: 600;
color: white;
text-align: center;
}
.action-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.action-card {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
padding: 20px;
cursor: pointer;
transition: all 0.2s ease;
backdrop-filter: blur(10px);
}
.action-card:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
.card-content {
display: flex;
align-items: center;
gap: 16px;
}
.card-icon {
font-size: 24px;
flex-shrink: 0;
}
.card-text {
flex: 1;
}
.card-title {
margin: 0 0 4px 0;
font-size: 16px;
font-weight: 600;
color: white;
}
.card-description {
margin: 0;
font-size: 14px;
color: rgba(255, 255, 255, 0.8);
line-height: 1.4;
}
.card-arrow {
flex-shrink: 0;
color: rgba(255, 255, 255, 0.6);
font-size: 18px;
}
/* Mobile responsiveness */
@media (max-width: 768px) {
.home-view {
padding: 16px;
}
.welcome-section {
padding: 30px 16px;
}
.welcome-title {
font-size: 28px;
}
.welcome-subtitle {
font-size: 16px;
}
.action-grid {
grid-template-columns: 1fr;
}
.action-card {
padding: 16px;
}
.card-content {
gap: 12px;
}
.card-icon {
font-size: 20px;
}
.card-title {
font-size: 15px;
}
.card-description {
font-size: 13px;
}
}
</style>
Loading…
Cancel
Save