diff --git a/assets/css/app.css b/assets/css/app.css index c0efe7ae6..903282af0 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -384,6 +384,10 @@ small { background-image: url("data:image/svg+xml,"); } +.dark .text-muted { + color: var(--bs-gray-medium) !important; +} + .dark .form-select:disabled { opacity: 0.5; } @@ -474,3 +478,17 @@ input[type="time"]::-webkit-calendar-picker-indicator { width: 50% !important; } } + +html.app .hide-in-app { + display: none !important; +} + +.safe-area-inset { + padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) + env(safe-area-inset-left); +} + +.modal-dialog { + margin-top: max(var(--bs-modal-margin), env(safe-area-inset-top)); + margin-bottom: max(var(--bs-modal-margin), env(safe-area-inset-bottom)); +} diff --git a/assets/index.html b/assets/index.html index 29fc23694..7e4f2f4d5 100644 --- a/assets/index.html +++ b/assets/index.html @@ -8,6 +8,7 @@ + @@ -18,6 +19,7 @@ + evcc diff --git a/assets/js/app.js b/assets/js/app.js index 3b6877f7b..0f6903181 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -7,6 +7,7 @@ import setupRouter from "./router"; import setupI18n from "./i18n"; import featureflags from "./featureflags"; import { watchThemeChanges } from "./theme"; +import { appDetection, sendToApp } from "./utils/native"; // lazy load smoothscroll polyfill. mainly for safari < 15.4 if (!window.CSS.supports("scroll-behavior", "smooth")) { @@ -23,6 +24,7 @@ const app = createApp({ watch: { offline: function (value) { console.log(`we are ${value ? "offline" : "online"}`); + sendToApp({ type: value ? "offline" : "online" }); }, }, methods: { @@ -70,3 +72,4 @@ app.mixin(VueHeadMixin); window.app = app.mount("#app"); watchThemeChanges(); +appDetection(); diff --git a/assets/js/components/Site.vue b/assets/js/components/Site.vue index 45ddd5a54..ea9e03d2e 100644 --- a/assets/js/components/Site.vue +++ b/assets/js/components/Site.vue @@ -1,5 +1,5 @@ @@ -115,6 +110,7 @@ import "@h2d2/shopicons/es/regular/newtab"; import collector from "../mixins/collector"; import baseAPI from "../baseapi"; +import { isApp, sendToApp } from "../utils/native"; export default { name: "TopNavigation", @@ -130,6 +126,11 @@ export default { sponsorTokenExpires: Number, batteryConfigured: Boolean, }, + data() { + return { + isApp: isApp(), + }; + }, computed: { logoutCount() { return this.providerLogins.filter((login) => !login.loggedIn).length; @@ -186,6 +187,9 @@ export default { ); modal.show(); }, + openNativeSettings() { + sendToApp({ type: "settings" }); + }, }, }; diff --git a/assets/js/utils/native.js b/assets/js/utils/native.js new file mode 100644 index 000000000..fb5368992 --- /dev/null +++ b/assets/js/utils/native.js @@ -0,0 +1,14 @@ +export function isApp() { + return navigator.userAgent.includes("evcc/"); +} + +export function appDetection() { + if (isApp()) { + const $html = document.querySelector("html"); + $html.classList.add("app"); + } +} + +export function sendToApp(data) { + window.ReactNativeWebView?.postMessage(JSON.stringify(data)); +} diff --git a/assets/js/views/ChargingSessions.vue b/assets/js/views/ChargingSessions.vue index 58107b4a0..c84219375 100644 --- a/assets/js/views/ChargingSessions.vue +++ b/assets/js/views/ChargingSessions.vue @@ -1,9 +1,11 @@