223 lines
5.9 KiB
TypeScript
223 lines
5.9 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { dirname, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
import type { Plugin } from "vite";
|
|
import { VitePWA } from "vite-plugin-pwa";
|
|
|
|
const pwaDirectory = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const tauriIcons = resolve(pwaDirectory, "../tauri/src-tauri/icons");
|
|
const androidResources = resolve(
|
|
pwaDirectory,
|
|
"../tauri/src-tauri/gen/android/app/src/main/res",
|
|
);
|
|
|
|
function emitIcons(): Plugin {
|
|
const icons = [
|
|
{
|
|
fileName: "icons/icon-180.png",
|
|
source: resolve(tauriIcons, "ios/AppIcon-60x60@3x.png"),
|
|
},
|
|
{
|
|
fileName: "icons/icon-192.png",
|
|
source: resolve(androidResources, "mipmap-xxxhdpi/ic_launcher.png"),
|
|
},
|
|
{
|
|
fileName: "icons/icon-96.png",
|
|
source: resolve(androidResources, "mipmap-xhdpi/ic_launcher.png"),
|
|
},
|
|
{
|
|
fileName: "icons/icon-512.png",
|
|
source: resolve(tauriIcons, "icon.png"),
|
|
},
|
|
{
|
|
fileName: "icons/icon-maskable-512.png",
|
|
source: resolve(tauriIcons, "icon.png"),
|
|
},
|
|
{
|
|
fileName: "icons/icon-monochrome-432.png",
|
|
source: resolve(
|
|
androidResources,
|
|
"mipmap-xxxhdpi/ic_launcher_monochrome.png",
|
|
),
|
|
},
|
|
{
|
|
fileName: "icons/notification-badge.png",
|
|
source: resolve(androidResources, "drawable/ic_notification_small.png"),
|
|
},
|
|
];
|
|
|
|
return {
|
|
name: "tensamin-pwa-icons",
|
|
configureServer(server) {
|
|
server.middlewares.use((request, response, next) => {
|
|
const pathname = request.url
|
|
? new URL(request.url, "http://localhost").pathname.slice(1)
|
|
: "";
|
|
const icon = icons.find(({ fileName }) => fileName === pathname);
|
|
if (!icon) {
|
|
next();
|
|
return;
|
|
}
|
|
response.statusCode = 200;
|
|
response.setHeader("Content-Type", "image/png");
|
|
response.setHeader("Cache-Control", "no-cache");
|
|
response.end(readFileSync(icon.source));
|
|
});
|
|
},
|
|
generateBundle() {
|
|
for (const icon of icons) {
|
|
this.emitFile({
|
|
type: "asset",
|
|
fileName: icon.fileName,
|
|
source: readFileSync(icon.source),
|
|
});
|
|
}
|
|
},
|
|
transformIndexHtml: {
|
|
order: "post",
|
|
handler() {
|
|
return [
|
|
{
|
|
tag: "link",
|
|
attrs: {
|
|
rel: "apple-touch-icon",
|
|
sizes: "180x180",
|
|
href: "./icons/icon-180.png",
|
|
},
|
|
injectTo: "head",
|
|
},
|
|
{
|
|
tag: "meta",
|
|
attrs: { name: "apple-mobile-web-app-capable", content: "yes" },
|
|
injectTo: "head",
|
|
},
|
|
{
|
|
tag: "meta",
|
|
attrs: { name: "mobile-web-app-capable", content: "yes" },
|
|
injectTo: "head",
|
|
},
|
|
{
|
|
tag: "meta",
|
|
attrs: {
|
|
name: "apple-mobile-web-app-status-bar-style",
|
|
content: "black-translucent",
|
|
},
|
|
injectTo: "head",
|
|
},
|
|
{
|
|
tag: "meta",
|
|
attrs: {
|
|
name: "apple-mobile-web-app-title",
|
|
content: "Tensamin",
|
|
},
|
|
injectTo: "head",
|
|
},
|
|
{
|
|
tag: "meta",
|
|
attrs: { name: "theme-color", content: "#006a67" },
|
|
injectTo: "head",
|
|
},
|
|
];
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
export function tensaminPwa(): Plugin[] {
|
|
return [
|
|
emitIcons(),
|
|
...VitePWA({
|
|
strategies: "injectManifest",
|
|
srcDir: resolve(pwaDirectory, "src"),
|
|
filename: "serviceWorker.ts",
|
|
injectRegister: null,
|
|
registerType: "prompt",
|
|
buildBase: "/",
|
|
manifestFilename: "manifest.json",
|
|
includeAssets: ["favicon.ico", "icons/*.png"],
|
|
manifest: {
|
|
id: "/",
|
|
name: "Tensamin",
|
|
short_name: "Tensamin",
|
|
description: "Private messaging and calls with Tensamin.",
|
|
start_url: "/",
|
|
scope: "/",
|
|
display: "standalone",
|
|
display_override: ["window-controls-overlay", "standalone"],
|
|
background_color: "#001f1e",
|
|
theme_color: "#006a67",
|
|
categories: ["social", "communication"],
|
|
orientation: "any",
|
|
launch_handler: { client_mode: "focus-existing" },
|
|
icons: [
|
|
{
|
|
src: "icons/icon-192.png",
|
|
sizes: "192x192",
|
|
type: "image/png",
|
|
purpose: "any",
|
|
},
|
|
{
|
|
src: "icons/icon-512.png",
|
|
sizes: "512x512",
|
|
type: "image/png",
|
|
purpose: "any",
|
|
},
|
|
{
|
|
src: "icons/icon-maskable-512.png",
|
|
sizes: "512x512",
|
|
type: "image/png",
|
|
purpose: "maskable",
|
|
},
|
|
{
|
|
src: "icons/icon-monochrome-432.png",
|
|
sizes: "432x432",
|
|
type: "image/png",
|
|
purpose: "monochrome",
|
|
},
|
|
],
|
|
shortcuts: [
|
|
{
|
|
name: "Chats",
|
|
short_name: "Chats",
|
|
url: "/",
|
|
icons: [
|
|
{
|
|
src: "icons/icon-96.png",
|
|
sizes: "96x96",
|
|
type: "image/png",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Settings",
|
|
short_name: "Settings",
|
|
url: "/settings",
|
|
icons: [
|
|
{
|
|
src: "icons/icon-96.png",
|
|
sizes: "96x96",
|
|
type: "image/png",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
file_handlers: [
|
|
{
|
|
action: "/login",
|
|
accept: { "application/x-tensamin-user": [".tu"] },
|
|
},
|
|
],
|
|
},
|
|
injectManifest: {
|
|
globPatterns: ["**/*.{js,css,html,ico,png,svg,woff2,wasm,mp3,wav}"],
|
|
globIgnores: ["assets/v2/**"],
|
|
maximumFileSizeToCacheInBytes: 15 * 1024 * 1024,
|
|
},
|
|
devOptions: {
|
|
enabled: true,
|
|
type: "module",
|
|
},
|
|
}),
|
|
];
|
|
}
|