diff --git a/main.js b/main.js index 624219e..fe0171e 100644 --- a/main.js +++ b/main.js @@ -4,6 +4,8 @@ const si = require('systeminformation'); const packageJSON = require('./package.json'); const { updateElectronApp } = require('update-electron-app'); +const crypto = require('crypto'); + const {initializeDatabase, captureDataPoint, getDataPoints, deleteDataPoint} = require('./src/system/database'); const {initializeAppData, storeAppData} = require('./src/system/configuration'); @@ -115,11 +117,17 @@ app.whenReady().then(async () => { } // Get system initialization information once the application is ready + // We hash the UUID to prevent tracking of individual users ipcMain.handle('application-ready', async () => { let uuid = null; + let platform = null; await si.system().then(data => uuid = data.uuid); + await si.osInfo().then(data => platform = data.platform); + const hash = crypto.createHash('sha256'); + hash.update(uuid); return { - 'uuid': uuid, + 'uuid': hash.digest('hex'), + 'platform': platform, 'version': packageJSON.version, } }); diff --git a/package.json b/package.json index 153e871..9408253 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "author": "RCKT Software, LLC.", "description": "An open-source progress tracker that predicts when you'll reach your goals", "private": true, - "version": "1.3.139", + "version": "1.3.140", "main": "main.js", "repository": "github:RCKT-Software/telemetry", "scripts": { diff --git a/src/App.vue b/src/App.vue index f0fa909..b16163c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -114,22 +114,46 @@ import Welcome from "./components/layout/welcome.vue"; import {Database, History, Plus, Table2, X} from "lucide-vue-next"; +const appDataStore = useAppDataStore(); +const modalStore = useModalStore(); +const interfaceStore = useInterfaceStore(); + const systemInformation = ref({ version: null, - uuid: null + uuid: null, + platform: null, }); -; /** * Get system information when available + * Send anonymous usage data once per minute */ onMounted(async () => { systemInformation.value = await window["electronAPI"].getSystemInformation(); + await sendAnonymousUsageData(); + setInterval(async () => { + await sendAnonymousUsageData(); + }, 1000 * 60); }); -const appDataStore = useAppDataStore(); -const modalStore = useModalStore(); -const interfaceStore = useInterfaceStore(); +/** + * Sends anonymous usage data to the server + * @returns {Promise} + */ +const sendAnonymousUsageData = async () => { + await fetch('https://telemetry.software/api/usage', { + method: 'POST', + body: JSON.stringify({ + deviceId: systemInformation.value.uuid, + platform: systemInformation.value.platform, + version: systemInformation.value.version, + numCollections: appDataStore.collections.length, + numTrackers: appDataStore.numTrackers, + numGoals: appDataStore.numGoals, + numDataPoints: appDataStore.numDataPoints, + }) + }); +} const rootStyles = computed(() => { if (appDataStore.darkMode) { diff --git a/src/stores/appData.js b/src/stores/appData.js index abf2cd9..6c26ef8 100644 --- a/src/stores/appData.js +++ b/src/stores/appData.js @@ -89,6 +89,43 @@ export const useAppDataStore = defineStore('appData', () => { } } + /** + * The total number of trackers across all collections + */ + const numTrackers = computed(() => { + let count = 0; + for (let collection of collections.value) { + count += collection.trackers.length; + } + return count; + }); + + /** + * The total number of goals across all trackers + */ + const numGoals = computed(() => { + let count = 0; + for (let collection of collections.value) { + for (let tracker of collection.trackers) { + count += tracker.goals.length; + } + } + return count; + }); + + /** + * The total number of data points across all trackers + */ + const numDataPoints = computed(() => { + let count = 0; + for (let collection of collections.value) { + for (let tracker of collection.trackers) { + count += tracker.recentDataPoints.length; + } + } + return count; + }) + /** * A flag indicating whether the welcome screen should be shown when the user visits an empty collection */ @@ -104,6 +141,9 @@ export const useAppDataStore = defineStore('appData', () => { getTrackerById, addCollection, deleteCollection, - showWelcome + showWelcome, + numTrackers, + numGoals, + numDataPoints }; })