diff --git a/app/src/assets/home.less b/app/src/assets/home.less index 5b86a0b..534dddb 100644 --- a/app/src/assets/home.less +++ b/app/src/assets/home.less @@ -413,9 +413,28 @@ } .version { + display: flex; + flex-direction: row; + align-items: center; user-select: none; - text-align: center; font-size: 14px; color: hsl(var(--text-secondary)); transform: translateY(4px); + width: max-content; + margin: 0 auto; + + svg { + margin-right: 2px; + padding: 2px; + width: 24px; + height: 24px; + color: hsl(var(--text-secondary)); + cursor: pointer; + transition: 0.25s; + transform: translateY(1px); + + &:hover { + color: hsl(var(--text)); + } + } } diff --git a/app/src/components/home/ChatWrapper.tsx b/app/src/components/home/ChatWrapper.tsx index 0d45996..0b3d8c2 100644 --- a/app/src/components/home/ChatWrapper.tsx +++ b/app/src/components/home/ChatWrapper.tsx @@ -10,7 +10,7 @@ import { setWeb, } from "../../store/chat.ts"; import { manager } from "../../conversation/manager.ts"; -import { formatMessage } from "../../utils.ts"; +import {formatMessage, triggerInstallApp} from "../../utils.ts"; import ChatInterface from "./ChatInterface.tsx"; import { Button } from "../ui/button.tsx"; import router from "../../router.tsx"; @@ -39,6 +39,7 @@ import { DialogTitle, } from "../ui/dialog.tsx"; import {version} from "../../conf.ts"; +import {AppIcon} from "../../icons/icons.tsx"; function ChatSpace() { const [open, setOpen] = useState(false); @@ -230,6 +231,13 @@ function ChatWrapper() {
+ + + + + + + chatnio v{version}
diff --git a/app/src/conf.ts b/app/src/conf.ts index a15ca52..435c27d 100644 --- a/app/src/conf.ts +++ b/app/src/conf.ts @@ -1,7 +1,7 @@ import axios from "axios"; import { Model } from "./conversation/types.ts"; -export const version = "3.5.14"; +export const version = "3.5.15"; export const dev: boolean = window.location.hostname === "localhost"; export const deploy: boolean = true; export let rest_api: string = "http://localhost:8094"; diff --git a/app/src/types/service.d.ts b/app/src/types/service.d.ts index 7c61797..942ed85 100644 --- a/app/src/types/service.d.ts +++ b/app/src/types/service.d.ts @@ -13,3 +13,12 @@ declare module "virtual:pwa-register/react" { onRegistered: (registration: ServiceWorkerRegistration) => void; }; } + +interface BeforeInstallPromptEvent extends Event { + readonly platforms: string[]; + readonly userChoice: Promise<{ + outcome: "accepted" | "dismissed"; + platform: string; + }>; + prompt(): Promise; +} diff --git a/app/src/utils.ts b/app/src/utils.ts index 0a7e8b4..07abe70 100644 --- a/app/src/utils.ts +++ b/app/src/utils.ts @@ -1,12 +1,33 @@ import React, { useEffect } from "react"; import { FileObject } from "./components/FileProvider.tsx"; +export let event: BeforeInstallPromptEvent | undefined; export let mobile = isMobile(); window.addEventListener("resize", () => { mobile = isMobile(); }); + +window.addEventListener('beforeinstallprompt', (e: Event) => { + e.preventDefault(); + event = (e as BeforeInstallPromptEvent); +}); + +export function triggerInstallApp() { + if (!event) return; + try { + event.prompt(); + event.userChoice.then((choice: any) => { + console.debug(`[service] installed app (status: ${choice.outcome})`); + }); + } catch (err) { + console.debug("[service] install app error", err); + } + + event = undefined; +} + export function isMobile(): boolean { return ( (document.documentElement.clientWidth || window.innerWidth) <= 668 ||