forked from trent_larson/crowd-funder-for-time-pwa
Multi-build support; tested successfully for Electron
This commit is contained in:
247
src/App.vue
247
src/App.vue
@@ -319,107 +319,202 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Vue, Component } from "vue-facing-decorator";
|
||||
|
||||
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "./db/index";
|
||||
import { NotificationIface } from "./constants/app";
|
||||
|
||||
interface Settings {
|
||||
notifyingNewActivityTime?: string;
|
||||
notifyingReminderTime?: string;
|
||||
}
|
||||
|
||||
@Component
|
||||
export default class App extends Vue {
|
||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||
|
||||
stopAsking = false;
|
||||
|
||||
async turnOffNotifications(notification: NotificationIface) {
|
||||
let subscription: object | null = null;
|
||||
created() {
|
||||
console.log(
|
||||
"Component created: Reactivity set up.",
|
||||
window.location.pathname,
|
||||
);
|
||||
}
|
||||
|
||||
beforeCreate() {
|
||||
console.log("Component beforeCreate: Instance initialized.");
|
||||
}
|
||||
|
||||
beforeMount() {
|
||||
console.log("Component beforeMount: Template is about to be rendered.");
|
||||
}
|
||||
|
||||
mounted() {
|
||||
console.log("Component mounted: Template is now rendered.");
|
||||
}
|
||||
|
||||
beforeUpdate() {
|
||||
console.log("Component beforeUpdate: DOM is about to be updated.");
|
||||
}
|
||||
|
||||
updated() {
|
||||
console.log("Component updated: DOM has been updated.");
|
||||
}
|
||||
|
||||
beforeUnmount() {
|
||||
console.log("Component beforeUnmount: Cleaning up before removal.");
|
||||
}
|
||||
|
||||
unmounted() {
|
||||
console.log("Component unmounted: Component removed from the DOM.");
|
||||
}
|
||||
|
||||
async turnOffNotifications(
|
||||
notification: NotificationIface,
|
||||
): Promise<boolean> {
|
||||
console.log("Starting turnOffNotifications...");
|
||||
let subscription: PushSubscriptionJSON | null = null;
|
||||
let allGoingOff = false;
|
||||
const settings = await retrieveSettingsForActiveAccount();
|
||||
const notifyingNewActivity = !!settings?.notifyingNewActivityTime;
|
||||
const notifyingReminder = !!settings?.notifyingReminderTime;
|
||||
if (!notifyingNewActivity || !notifyingReminder) {
|
||||
// the other notification is already off, so fully unsubscribe now
|
||||
allGoingOff = true;
|
||||
}
|
||||
|
||||
await navigator.serviceWorker?.ready
|
||||
.then((registration) => {
|
||||
return registration.pushManager.getSubscription();
|
||||
})
|
||||
.then(async (subscript: PushSubscription | null) => {
|
||||
if (subscript) {
|
||||
subscription = subscript.toJSON();
|
||||
if (allGoingOff) {
|
||||
await subscript.unsubscribe();
|
||||
try {
|
||||
console.log("Retrieving settings for the active account...");
|
||||
const settings: Settings = await retrieveSettingsForActiveAccount();
|
||||
console.log("Retrieved settings:", settings);
|
||||
|
||||
const notifyingNewActivity = !!settings?.notifyingNewActivityTime;
|
||||
const notifyingReminder = !!settings?.notifyingReminderTime;
|
||||
|
||||
if (!notifyingNewActivity || !notifyingReminder) {
|
||||
allGoingOff = true;
|
||||
console.log("Both notifications are being turned off.");
|
||||
}
|
||||
|
||||
console.log("Checking service worker readiness...");
|
||||
await navigator.serviceWorker?.ready
|
||||
.then((registration) => {
|
||||
console.log("Service worker is ready. Fetching subscription...");
|
||||
return registration.pushManager.getSubscription();
|
||||
})
|
||||
.then(async (subscript: PushSubscription | null) => {
|
||||
if (subscript) {
|
||||
subscription = subscript.toJSON();
|
||||
console.log("PushSubscription retrieved:", subscription);
|
||||
|
||||
if (allGoingOff) {
|
||||
console.log("Unsubscribing from push notifications...");
|
||||
await subscript.unsubscribe();
|
||||
console.log("Successfully unsubscribed.");
|
||||
}
|
||||
} else {
|
||||
logConsoleAndDb("Subscription object is not available.");
|
||||
console.log("No subscription found.");
|
||||
}
|
||||
} else {
|
||||
logConsoleAndDb("Subscription object is not available.");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
logConsoleAndDb(
|
||||
"Push provider server communication failed: " + JSON.stringify(error),
|
||||
true,
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
logConsoleAndDb(
|
||||
"Push provider server communication failed: " +
|
||||
JSON.stringify(error),
|
||||
true,
|
||||
);
|
||||
console.error("Error during subscription fetch:", error);
|
||||
});
|
||||
|
||||
if (!subscription) {
|
||||
console.log("No subscription available. Notifying user...");
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "info",
|
||||
title: "Finished",
|
||||
text: "Notifications are off.",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
console.log("Exiting as there is no subscription to process.");
|
||||
return true;
|
||||
}
|
||||
|
||||
const serverSubscription = {
|
||||
...subscription,
|
||||
};
|
||||
if (!allGoingOff) {
|
||||
serverSubscription["notifyType"] = notification.title;
|
||||
console.log(
|
||||
`Server subscription updated with notifyType: ${notification.title}`,
|
||||
);
|
||||
}
|
||||
|
||||
console.log("Sending unsubscribe request to the server...");
|
||||
const pushServerSuccess = await fetch("/web-push/unsubscribe", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(serverSubscription),
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.text();
|
||||
logConsoleAndDb(
|
||||
`Push server failed: ${response.status} ${errorBody}`,
|
||||
true,
|
||||
);
|
||||
console.error("Push server error response:", errorBody);
|
||||
}
|
||||
console.log(`Server response status: ${response.status}`);
|
||||
return response.ok;
|
||||
})
|
||||
.catch((error) => {
|
||||
logConsoleAndDb(
|
||||
"Push server communication failed: " + JSON.stringify(error),
|
||||
true,
|
||||
);
|
||||
console.error("Error during server communication:", error);
|
||||
return false;
|
||||
});
|
||||
|
||||
const message = pushServerSuccess
|
||||
? "Notification is off."
|
||||
: "Notification is still on. Try to turn it off again.";
|
||||
console.log("Server response processed. Message:", message);
|
||||
|
||||
if (!subscription) {
|
||||
// there is no endpoint or auth for the server to compare, so we're done
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "info",
|
||||
title: "Finished",
|
||||
text: "Notifications are off.", // a different message so I know there are none stored
|
||||
text: message,
|
||||
},
|
||||
5000,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// clone in order to get only the properties and allow stringify to work
|
||||
const serverSubscription = {
|
||||
...subscription,
|
||||
};
|
||||
if (!allGoingOff) {
|
||||
serverSubscription["notifyType"] = notification.title;
|
||||
}
|
||||
const pushServerSuccess = await fetch("/web-push/unsubscribe", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(serverSubscription),
|
||||
})
|
||||
.then((response) => {
|
||||
return response.ok;
|
||||
})
|
||||
.catch((error) => {
|
||||
logConsoleAndDb(
|
||||
"Push server communication failed: " + JSON.stringify(error),
|
||||
true,
|
||||
);
|
||||
return false;
|
||||
});
|
||||
if (notification.callback) {
|
||||
console.log("Executing notification callback...");
|
||||
notification.callback(pushServerSuccess);
|
||||
}
|
||||
|
||||
let message;
|
||||
if (pushServerSuccess) {
|
||||
message = "Notification is off.";
|
||||
} else {
|
||||
message = "Notification is still on. Try to turn it off again.";
|
||||
}
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "info",
|
||||
title: "Finished",
|
||||
text: message,
|
||||
},
|
||||
5000,
|
||||
);
|
||||
console.log(
|
||||
"Completed turnOffNotifications with success:",
|
||||
pushServerSuccess,
|
||||
);
|
||||
return pushServerSuccess;
|
||||
} catch (error) {
|
||||
logConsoleAndDb(
|
||||
"Error turning off notifications: " + JSON.stringify(error),
|
||||
true,
|
||||
);
|
||||
console.error("Critical error in turnOffNotifications:", error);
|
||||
|
||||
if (notification.callback) {
|
||||
// it's OK if the local notifications are still on (especially if the other notification is on)
|
||||
notification.callback(pushServerSuccess);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "error",
|
||||
title: "Error",
|
||||
text: "Failed to turn off notifications. Please try again.",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { createAvatar, StyleOptions } from "@dicebear/core";
|
||||
import { avataaars } from "@dicebear/collection";
|
||||
import { Vue, Component, Prop } from "vue-facing-decorator";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
import { Contact } from "../db/tables/contacts";
|
||||
|
||||
@Component
|
||||
export default class EntityIcon extends Vue {
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<script lang="ts">
|
||||
import { Vue, Component } from "vue-facing-decorator";
|
||||
|
||||
import { NotificationIface } from "@/constants/app";
|
||||
import { NotificationIface } from "../constants/app";
|
||||
|
||||
@Component
|
||||
export default class InviteDialog extends Vue {
|
||||
|
||||
51
src/electron/main.js
Normal file
51
src/electron/main.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const { app, BrowserWindow } = require("electron");
|
||||
const path = require("path");
|
||||
|
||||
let mainWindow;
|
||||
|
||||
app.on("ready", () => {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
//preload: path.join(__dirname, "preload.js"),
|
||||
contextIsolation: true, // Security setting
|
||||
},
|
||||
});
|
||||
|
||||
const indexPath = path.join(
|
||||
__dirname,
|
||||
"../../",
|
||||
"dist-electron",
|
||||
"index.html",
|
||||
);
|
||||
|
||||
console.log("Loading Vue app from:", indexPath);
|
||||
mainWindow.webContents.openDevTools();
|
||||
|
||||
mainWindow.webContents.on(
|
||||
"did-fail-load",
|
||||
(event, errorCode, errorDescription, validatedURL) => {
|
||||
console.error(
|
||||
"Failed to load:",
|
||||
validatedURL,
|
||||
"Error:",
|
||||
errorDescription,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
mainWindow.webContents.on("console-message", (event, level, message) => {
|
||||
console.log(`[Renderer] ${message}`);
|
||||
});
|
||||
|
||||
mainWindow.loadFile(indexPath).catch((err) => {
|
||||
console.error("Failed to load index.html:", err);
|
||||
});
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
5
src/electron/preload.js
Normal file
5
src/electron/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge } = require("electron");
|
||||
|
||||
contextBridge.exposeInMainWorld("api", {
|
||||
logMessage: (message) => console.log(`[Electron]: ${message}`),
|
||||
});
|
||||
@@ -191,7 +191,7 @@ function setupGlobalErrorHandler(app: VueApp) {
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
console.log("Bootstrapping Vue app...");
|
||||
const app = createApp(App)
|
||||
.component("fa", FontAwesomeIcon)
|
||||
.component("camera", Camera)
|
||||
@@ -203,3 +203,4 @@ const app = createApp(App)
|
||||
setupGlobalErrorHandler(app);
|
||||
|
||||
app.mount("#app");
|
||||
console.log("Vue app mounted.");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
createRouter,
|
||||
createWebHistory,
|
||||
createMemoryHistory,
|
||||
NavigationGuardNext,
|
||||
RouteLocationNormalized,
|
||||
RouteRecordRaw,
|
||||
@@ -21,6 +22,9 @@ const enterOrStart = async (
|
||||
// one of the few times we use accountsDBPromise directly; try to avoid more usage
|
||||
const accountsDB = await accountsDBPromise;
|
||||
const num_accounts = await accountsDB.accounts.count();
|
||||
|
||||
console.log("Number of accounts: ", num_accounts);
|
||||
|
||||
if (num_accounts > 0) {
|
||||
next();
|
||||
} else {
|
||||
@@ -255,12 +259,26 @@ const routes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
];
|
||||
|
||||
const isElectron = window.location.protocol === "file:"; // Check if running in Electron
|
||||
const initialPath = isElectron
|
||||
? window.location.pathname.replace("/dist-electron/index.html", "/")
|
||||
: window.location.pathname;
|
||||
|
||||
const history = isElectron
|
||||
? createMemoryHistory() // Memory history for Electron
|
||||
: createWebHistory("/"); // Add base path for web apps
|
||||
|
||||
/** @type {*} */
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
history,
|
||||
routes,
|
||||
});
|
||||
|
||||
console.log("Initial URL:", initialPath);
|
||||
|
||||
// Replace initial URL to start at `/` if necessary
|
||||
router.replace(initialPath || "/");
|
||||
|
||||
const errorHandler = (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: any,
|
||||
@@ -278,4 +296,12 @@ const errorHandler = (
|
||||
|
||||
router.onError(errorHandler); // Assign the error handler to the router instance
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log("Navigating to view:", to.name);
|
||||
console.log("From view:", from.name);
|
||||
next();
|
||||
});
|
||||
|
||||
console.log("Initial URL:", window.location.pathname);
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user