diff --git a/BUILDING.md b/BUILDING.md index ba981a8d..607bf60d 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -2743,6 +2743,45 @@ configuration files in the repository. --- +### 2025-08-26 - Capacitor Plugin Additions + +#### New Capacitor Plugins Added +- **Added**: `@capacitor/clipboard` v6.0.2 - Clipboard functionality for mobile platforms + - **Purpose**: Enable copy/paste operations on mobile devices + - **Platforms**: iOS and Android + - **Features**: Read/write clipboard content, text handling + - **Integration**: Automatically included in mobile builds + +- **Added**: `@capacitor/status-bar` v6.0.2 - Status bar management for mobile platforms + - **Purpose**: Control mobile device status bar appearance and behavior + - **Platforms**: iOS and Android + - **Features**: Status bar styling, visibility control, color management + - **Integration**: Automatically included in mobile builds + +#### Android Build System Updates +- **Modified**: `android/capacitor.settings.gradle` - Added new plugin project includes + - **Added**: `:capacitor-clipboard` project directory mapping + - **Added**: `:capacitor-status-bar` project directory mapping + - **Impact**: New plugins now properly integrated into Android build process + +#### Package Dependencies +- **Updated**: `package.json` - Added new Capacitor plugin dependencies +- **Updated**: `package-lock.json` - Locked dependency versions for consistency +- **Version**: All new plugins use Capacitor 6.x compatible versions + +#### Build Process Impact +- **No Breaking Changes**: Existing build commands continue to work unchanged +- **Enhanced Mobile Features**: New clipboard and status bar capabilities available +- **Automatic Integration**: Plugins automatically included in mobile builds +- **Platform Support**: Both iOS and Android builds now include new functionality + +#### Testing Requirements +- **Mobile Builds**: Verify new plugins integrate correctly in iOS and Android builds +- **Functionality**: Test clipboard operations and status bar management on devices +- **Fallback**: Ensure graceful degradation when plugins are unavailable + +--- + **Note**: This documentation is maintained alongside the build system. For the most up-to-date information, refer to the actual script files and Vite configuration files in the repository. diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index ec740be6..f1774d9f 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -13,8 +13,10 @@ dependencies { implementation project(':capacitor-mlkit-barcode-scanning') implementation project(':capacitor-app') implementation project(':capacitor-camera') + implementation project(':capacitor-clipboard') implementation project(':capacitor-filesystem') implementation project(':capacitor-share') + implementation project(':capacitor-status-bar') implementation project(':capawesome-capacitor-file-picker') } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 77641501..1d8ad70d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,6 +14,7 @@ android:label="@string/title_activity_main" android:launchMode="singleTask" android:screenOrientation="portrait" + android:windowSoftInputMode="adjustResize" android:theme="@style/AppTheme.NoActionBarLaunch"> diff --git a/android/app/src/main/assets/capacitor.plugins.json b/android/app/src/main/assets/capacitor.plugins.json index a95bd42f..72f18d8c 100644 --- a/android/app/src/main/assets/capacitor.plugins.json +++ b/android/app/src/main/assets/capacitor.plugins.json @@ -15,6 +15,10 @@ "pkg": "@capacitor/camera", "classpath": "com.capacitorjs.plugins.camera.CameraPlugin" }, + { + "pkg": "@capacitor/clipboard", + "classpath": "com.capacitorjs.plugins.clipboard.ClipboardPlugin" + }, { "pkg": "@capacitor/filesystem", "classpath": "com.capacitorjs.plugins.filesystem.FilesystemPlugin" @@ -23,6 +27,10 @@ "pkg": "@capacitor/share", "classpath": "com.capacitorjs.plugins.share.SharePlugin" }, + { + "pkg": "@capacitor/status-bar", + "classpath": "com.capacitorjs.plugins.statusbar.StatusBarPlugin" + }, { "pkg": "@capawesome/capacitor-file-picker", "classpath": "io.capawesome.capacitorjs.plugins.filepicker.FilePickerPlugin" diff --git a/android/app/src/main/java/app/timesafari/MainActivity.java b/android/app/src/main/java/app/timesafari/MainActivity.java index 12429d63..29224f45 100644 --- a/android/app/src/main/java/app/timesafari/MainActivity.java +++ b/android/app/src/main/java/app/timesafari/MainActivity.java @@ -1,7 +1,16 @@ package app.timesafari; import android.os.Bundle; +import android.view.View; +import android.view.WindowManager; +import android.view.WindowInsetsController; +import android.view.WindowInsets; +import android.os.Build; +import android.webkit.WebView; +import android.webkit.WebSettings; +import android.webkit.WebViewClient; import com.getcapacitor.BridgeActivity; +import app.timesafari.safearea.SafeAreaPlugin; //import com.getcapacitor.community.sqlite.SQLite; public class MainActivity extends BridgeActivity { @@ -9,7 +18,39 @@ public class MainActivity extends BridgeActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // Enable edge-to-edge display for modern Android + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Android 11+ (API 30+) + getWindow().setDecorFitsSystemWindows(false); + + // Set up system UI visibility for edge-to-edge + WindowInsetsController controller = getWindow().getInsetsController(); + if (controller != null) { + controller.setSystemBarsAppearance( + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS | + WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS, + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS | + WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS + ); + controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); + } + } else { + // Legacy Android (API 21-29) + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | + View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + ); + } + + // Register SafeArea plugin + registerPlugin(SafeAreaPlugin.class); + // Initialize SQLite //registerPlugin(SQLite.class); } + + } \ No newline at end of file diff --git a/android/app/src/main/java/app/timesafari/safearea/SafeAreaPlugin.java b/android/app/src/main/java/app/timesafari/safearea/SafeAreaPlugin.java new file mode 100644 index 00000000..cb433d57 --- /dev/null +++ b/android/app/src/main/java/app/timesafari/safearea/SafeAreaPlugin.java @@ -0,0 +1,44 @@ +package app.timesafari.safearea; + +import android.os.Build; +import android.view.WindowInsets; +import com.getcapacitor.JSObject; +import com.getcapacitor.Plugin; +import com.getcapacitor.PluginCall; +import com.getcapacitor.PluginMethod; +import com.getcapacitor.annotation.CapacitorPlugin; + +@CapacitorPlugin(name = "SafeArea") +public class SafeAreaPlugin extends Plugin { + + @PluginMethod + public void getSafeAreaInsets(PluginCall call) { + JSObject result = new JSObject(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + WindowInsets insets = getActivity().getWindow().getDecorView().getRootWindowInsets(); + if (insets != null) { + int top = insets.getInsets(WindowInsets.Type.statusBars()).top; + int bottom = insets.getInsets(WindowInsets.Type.navigationBars()).bottom; + int left = insets.getInsets(WindowInsets.Type.systemBars()).left; + int right = insets.getInsets(WindowInsets.Type.systemBars()).right; + + result.put("top", top); + result.put("bottom", bottom); + result.put("left", left); + result.put("right", right); + + call.resolve(result); + return; + } + } + + // Fallback values + result.put("top", 0); + result.put("bottom", 0); + result.put("left", 0); + result.put("right", 0); + + call.resolve(result); + } +} diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index be874e54..6a1ec3ca 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -18,5 +18,14 @@ \ No newline at end of file diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 3c06dfe7..891b5455 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -14,11 +14,17 @@ project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/ include ':capacitor-camera' project(':capacitor-camera').projectDir = new File('../node_modules/@capacitor/camera/android') +include ':capacitor-clipboard' +project(':capacitor-clipboard').projectDir = new File('../node_modules/@capacitor/clipboard/android') + include ':capacitor-filesystem' project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android') include ':capacitor-share' project(':capacitor-share').projectDir = new File('../node_modules/@capacitor/share/android') +include ':capacitor-status-bar' +project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') + include ':capawesome-capacitor-file-picker' project(':capawesome-capacitor-file-picker').projectDir = new File('../node_modules/@capawesome/capacitor-file-picker/android') diff --git a/doc/z-index-guide.md b/doc/z-index-guide.md new file mode 100644 index 00000000..49a5733a --- /dev/null +++ b/doc/z-index-guide.md @@ -0,0 +1,69 @@ +# Z-Index Guide — TimeSafari + +**Author**: Development Team +**Date**: 2025-08-25T19:38:09-08:00 +**Status**: 🎯 **ACTIVE** - Z-index layering standards + +## Objective +Establish consistent z-index values across the TimeSafari application to ensure proper layering of UI elements. + +## Result +This document defines the z-index hierarchy for all UI components. + +## Use/Run +Reference these values when implementing new components or modifying existing ones to maintain consistent layering. + +## Z-Index Hierarchy + +| Component | Z-Index | Usage | +|-----------|---------|-------| +| **Map** | `40` | Base map layer and map-related overlays | +| **QuickNav** | `50` | Quick navigation bottom bar | +| **Dialogs and Modals** | `100` | Modal dialogs, popups, and overlay content | +| **Notifications and Toasts** | `120` | System notifications, alerts, and toast messages | + +## Best Practices + +1. **Never exceed 120** - Keep the highest z-index reserved for critical notifications +2. **Use increments of 10** - Leave room for future additions between layers +3. **Document exceptions** - If you need a z-index outside this range, document the reason +4. **Test layering** - Verify z-index behavior across different screen sizes and devices + +## Common Pitfalls + +- **Avoid arbitrary values** - Don't use random z-index numbers +- **Don't nest high z-index** - Keep child elements within their parent's z-index range +- **Consider stacking context** - Remember that `position: relative` creates new stacking contexts + +## Next Steps + +| Owner | Task | Exit Criteria | Target Date | +|-------|------|---------------|-------------| +| Dev Team | Apply z-index classes to existing components | All components use defined z-index values | 2025-09-01 | + +## Competence Hooks + +- **Why this works**: Creates predictable layering hierarchy that prevents UI conflicts +- **Common pitfalls**: Using arbitrary z-index values or exceeding the defined range +- **Next skill unlock**: Learn about CSS stacking contexts and their impact on z-index +- **Teach-back**: Explain the z-index hierarchy to a team member without referencing this guide + +## Collaboration Hooks + +- **Reviewers**: Frontend team, UI/UX designers +- **Sign-off checklist**: + - [ ] All new components follow z-index guidelines + - [ ] Existing components updated to use defined values + - [ ] Cross-browser testing completed + - [ ] Mobile responsiveness verified + +## Assumptions & Limits + +- Assumes modern browser support for z-index +- Limited to 4 defined layers (expandable if needed) +- Requires team discipline to maintain consistency + +## References + +- [MDN Z-Index Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index) +- [CSS Stacking Context Guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context) diff --git a/ios/App/Podfile b/ios/App/Podfile index da98dfe6..efae46b4 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -15,8 +15,10 @@ def capacitor_pods pod 'CapacitorMlkitBarcodeScanning', :path => '../../node_modules/@capacitor-mlkit/barcode-scanning' pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app' pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera' + pod 'CapacitorClipboard', :path => '../../node_modules/@capacitor/clipboard' pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem' pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share' + pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar' pod 'CapawesomeCapacitorFilePicker', :path => '../../node_modules/@capawesome/capacitor-file-picker' end diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index fdd82e86..ab5cb59e 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -5,6 +5,8 @@ PODS: - Capacitor - CapacitorCamera (6.1.2): - Capacitor + - CapacitorClipboard (6.0.2): + - Capacitor - CapacitorCommunitySqlite (6.0.2): - Capacitor - SQLCipher @@ -17,6 +19,8 @@ PODS: - GoogleMLKit/BarcodeScanning (= 5.0.0) - CapacitorShare (6.0.3): - Capacitor + - CapacitorStatusBar (6.0.2): + - Capacitor - CapawesomeCapacitorFilePicker (6.2.0): - Capacitor - GoogleDataTransport (9.4.1): @@ -88,11 +92,13 @@ DEPENDENCIES: - "Capacitor (from `../../node_modules/@capacitor/ios`)" - "CapacitorApp (from `../../node_modules/@capacitor/app`)" - "CapacitorCamera (from `../../node_modules/@capacitor/camera`)" + - "CapacitorClipboard (from `../../node_modules/@capacitor/clipboard`)" - "CapacitorCommunitySqlite (from `../../node_modules/@capacitor-community/sqlite`)" - "CapacitorCordova (from `../../node_modules/@capacitor/ios`)" - "CapacitorFilesystem (from `../../node_modules/@capacitor/filesystem`)" - "CapacitorMlkitBarcodeScanning (from `../../node_modules/@capacitor-mlkit/barcode-scanning`)" - "CapacitorShare (from `../../node_modules/@capacitor/share`)" + - "CapacitorStatusBar (from `../../node_modules/@capacitor/status-bar`)" - "CapawesomeCapacitorFilePicker (from `../../node_modules/@capawesome/capacitor-file-picker`)" SPEC REPOS: @@ -119,6 +125,8 @@ EXTERNAL SOURCES: :path: "../../node_modules/@capacitor/app" CapacitorCamera: :path: "../../node_modules/@capacitor/camera" + CapacitorClipboard: + :path: "../../node_modules/@capacitor/clipboard" CapacitorCommunitySqlite: :path: "../../node_modules/@capacitor-community/sqlite" CapacitorCordova: @@ -129,6 +137,8 @@ EXTERNAL SOURCES: :path: "../../node_modules/@capacitor-mlkit/barcode-scanning" CapacitorShare: :path: "../../node_modules/@capacitor/share" + CapacitorStatusBar: + :path: "../../node_modules/@capacitor/status-bar" CapawesomeCapacitorFilePicker: :path: "../../node_modules/@capawesome/capacitor-file-picker" @@ -136,11 +146,13 @@ SPEC CHECKSUMS: Capacitor: c95400d761e376be9da6be5a05f226c0e865cebf CapacitorApp: e1e6b7d05e444d593ca16fd6d76f2b7c48b5aea7 CapacitorCamera: 9bc7b005d0e6f1d5f525b8137045b60cffffce79 + CapacitorClipboard: 4443c3cdb7c77b1533dfe3ff0f9f7756aa8579df CapacitorCommunitySqlite: 0299d20f4b00c2e6aa485a1d8932656753937b9b CapacitorCordova: 8d93e14982f440181be7304aa9559ca631d77fff CapacitorFilesystem: 59270a63c60836248812671aa3b15df673fbaf74 CapacitorMlkitBarcodeScanning: 7652be9c7922f39203a361de735d340ae37e134e CapacitorShare: d2a742baec21c8f3b92b361a2fbd2401cdd8288e + CapacitorStatusBar: b16799a26320ffa52f6c8b01737d5a95bbb8f3eb CapawesomeCapacitorFilePicker: c40822f0a39f86855321943c7829d52bca7f01bd GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleMLKit: 90ba06e028795a50261f29500d238d6061538711 @@ -157,6 +169,6 @@ SPEC CHECKSUMS: SQLCipher: 31878d8ebd27e5c96db0b7cb695c96e9f8ad77da ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c -PODFILE CHECKSUM: f987510f7383b04a1b09ea8472bdadcd88b6c924 +PODFILE CHECKSUM: 5fa870b031c7c4e0733e2f96deaf81866c75ff7d COCOAPODS: 1.16.2 diff --git a/package-lock.json b/package-lock.json index fea161a9..bf867511 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,12 @@ "@capacitor/app": "^6.0.0", "@capacitor/camera": "^6.0.0", "@capacitor/cli": "^6.2.0", + "@capacitor/clipboard": "^6.0.2", "@capacitor/core": "^6.2.0", "@capacitor/filesystem": "^6.0.0", "@capacitor/ios": "^6.2.0", "@capacitor/share": "^6.0.3", + "@capacitor/status-bar": "^6.0.2", "@capawesome/capacitor-file-picker": "^6.2.0", "@dicebear/collection": "^5.4.1", "@dicebear/core": "^5.4.1", @@ -2301,6 +2303,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@capacitor/clipboard": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/clipboard/-/clipboard-6.0.2.tgz", + "integrity": "sha512-jQ6UeFra5NP58THNZNb7HtzOZU7cHsjgrbQGVuMTgsK1uTILZpNeh+pfqHbKggba6KaNh5DAsJvEVQGpIR1VBA==", + "peerDependencies": { + "@capacitor/core": "^6.0.0" + } + }, "node_modules/@capacitor/core": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.1.tgz", @@ -2337,6 +2347,14 @@ "@capacitor/core": "^6.0.0" } }, + "node_modules/@capacitor/status-bar": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-6.0.2.tgz", + "integrity": "sha512-AmRIX6QvFemItlY7/69ARkIAqitRQqJ2qwgZmD1KqgFb78pH+XFXm1guvS/a8CuOOm/IqZ4ddDbl20yxtBqzGA==", + "peerDependencies": { + "@capacitor/core": "^6.0.0" + } + }, "node_modules/@capawesome/capacitor-file-picker": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@capawesome/capacitor-file-picker/-/capacitor-file-picker-6.2.0.tgz", diff --git a/package.json b/package.json index d3b86aa3..16c055c5 100644 --- a/package.json +++ b/package.json @@ -145,10 +145,12 @@ "@capacitor/app": "^6.0.0", "@capacitor/camera": "^6.0.0", "@capacitor/cli": "^6.2.0", + "@capacitor/clipboard": "^6.0.2", "@capacitor/core": "^6.2.0", "@capacitor/filesystem": "^6.0.0", "@capacitor/ios": "^6.2.0", "@capacitor/share": "^6.0.3", + "@capacitor/status-bar": "^6.0.2", "@capawesome/capacitor-file-picker": "^6.2.0", "@dicebear/collection": "^5.4.1", "@dicebear/core": "^5.4.1", diff --git a/src/App.vue b/src/App.vue index 8bd39b52..35457383 100644 --- a/src/App.vue +++ b/src/App.vue @@ -4,7 +4,7 @@
-
+
#Content { - padding-left: max(1.5rem, env(safe-area-inset-left)); - padding-right: max(1.5rem, env(safe-area-inset-right)); - padding-top: max(1.5rem, env(safe-area-inset-top)); - padding-bottom: max(1.5rem, env(safe-area-inset-bottom)); + padding-left: max( + 1.5rem, + env(safe-area-inset-left), + var(--safe-area-inset-left, 0px) + ); + padding-right: max( + 1.5rem, + env(safe-area-inset-right), + var(--safe-area-inset-right, 0px) + ); + padding-top: max( + 1.5rem, + env(safe-area-inset-top), + var(--safe-area-inset-top, 0px) + ); + padding-bottom: max( + 1.5rem, + env(safe-area-inset-bottom), + var(--safe-area-inset-bottom, 0px) + ); } #QuickNav ~ #Content { - padding-bottom: calc(env(safe-area-inset-bottom) + 6.333rem); + padding-bottom: calc( + max(env(safe-area-inset-bottom), var(--safe-area-inset-bottom, 0px)) + + 6.333rem + ); } diff --git a/src/assets/styles/tailwind.css b/src/assets/styles/tailwind.css index 60f6579d..f6457ff3 100644 --- a/src/assets/styles/tailwind.css +++ b/src/assets/styles/tailwind.css @@ -14,4 +14,12 @@ transform: translateX(100%); background-color: #FFF !important; } + + .dialog-overlay { + @apply z-[100] fixed inset-0 bg-black/50 flex justify-center items-center p-6; + } + + .dialog { + @apply bg-white p-4 rounded-lg w-full max-w-lg; + } } \ No newline at end of file diff --git a/src/components/ContactNameDialog.vue b/src/components/ContactNameDialog.vue index e0f715ea..3eb116cf 100644 --- a/src/components/ContactNameDialog.vue +++ b/src/components/ContactNameDialog.vue @@ -1,7 +1,7 @@