diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index e1e9924e..f1774d9f 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -16,6 +16,7 @@ dependencies { 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 6f389366..72f18d8c 100644 --- a/android/app/src/main/assets/capacitor.plugins.json +++ b/android/app/src/main/assets/capacitor.plugins.json @@ -27,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 188fdd40..891b5455 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -23,5 +23,8 @@ project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacit 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/ios/App/Podfile b/ios/App/Podfile index 5c94c24a..efae46b4 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -18,6 +18,7 @@ def capacitor_pods 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 eb9dd861..ab5cb59e 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -19,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): @@ -96,6 +98,7 @@ DEPENDENCIES: - "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: @@ -134,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" @@ -147,6 +152,7 @@ SPEC CHECKSUMS: CapacitorFilesystem: 59270a63c60836248812671aa3b15df673fbaf74 CapacitorMlkitBarcodeScanning: 7652be9c7922f39203a361de735d340ae37e134e CapacitorShare: d2a742baec21c8f3b92b361a2fbd2401cdd8288e + CapacitorStatusBar: b16799a26320ffa52f6c8b01737d5a95bbb8f3eb CapawesomeCapacitorFilePicker: c40822f0a39f86855321943c7829d52bca7f01bd GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleMLKit: 90ba06e028795a50261f29500d238d6061538711 @@ -163,6 +169,6 @@ SPEC CHECKSUMS: SQLCipher: 31878d8ebd27e5c96db0b7cb695c96e9f8ad77da ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c -PODFILE CHECKSUM: 60f54b19c5a7a07343ab5ba9e5db49019fd86aa0 +PODFILE CHECKSUM: 5fa870b031c7c4e0733e2f96deaf81866c75ff7d COCOAPODS: 1.16.2 diff --git a/package-lock.json b/package-lock.json index 48ffb61d..bf867511 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@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", @@ -2346,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 55357be2..16c055c5 100644 --- a/package.json +++ b/package.json @@ -150,6 +150,7 @@ "@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 fd1cc9aa..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/components/PhotoDialog.vue b/src/components/PhotoDialog.vue index fb110359..54511f67 100644 --- a/src/components/PhotoDialog.vue +++ b/src/components/PhotoDialog.vue @@ -10,7 +10,7 @@ Comprehensive error handling * * @author Matthew Raymer * @version 1.0.0 * @file PhotoDialog.vue */