Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/background/heartbeat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getActiveWindowTab, getTab, getTabs } from './helpers'
import config from '../config'
import { AWClient, IEvent } from 'aw-client'
import { getBucketId, sendHeartbeat } from './client'
import { getEnabled, getHeartbeatData, setHeartbeatData } from '../storage'
import { getEnabled, getHeartbeatData, setHeartbeatData, getDisplayProfileName } from '../storage'
import deepEqual from 'deep-equal'

async function heartbeat(
Expand All @@ -28,12 +28,15 @@ async function heartbeat(
}

const now = new Date()
const profileName = await getDisplayProfileName()

const data: IEvent['data'] = {
url: tab.url,
title: tab.title,
audible: tab.audible ?? false,
incognito: tab.incognito,
tabCount: tabCount,
profileName: profileName,
}
const previousData = await getHeartbeatData()
if (previousData && !deepEqual(previousData, data)) {
Expand Down
7 changes: 7 additions & 0 deletions src/background/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
setEnabled,
setHostname,
waitForEnabled,
generateProfileIdentifier,
} from '../storage'

async function getIsConsentRequired() {
Expand All @@ -34,6 +35,11 @@ async function autodetectHostname() {
}
}

async function initializeProfileIdentifier() {
await generateProfileIdentifier()
console.debug('Profile identifier initialized')
}

/** Init */
console.info('Starting...')

Expand All @@ -58,6 +64,7 @@ browser.runtime.onInstalled.addListener(async () => {
}

await autodetectHostname()
await initializeProfileIdentifier()
})

console.debug('Creating alarms and tab listeners')
Expand Down
14 changes: 14 additions & 0 deletions src/settings/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,20 @@
/>
</div>

<div>
<label for="profileName">
<strong>Profile Name:</strong>
</label>

<input
type="text"
id="profileName"
name="profileName"
pattern="[a-zA-Z0-9_.\- ]*"
placeholder="Custom profile name (optional)"
/>
</div>

<div>
<button type="submit">Save</button>
</div>
Expand Down
16 changes: 16 additions & 0 deletions src/settings/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
setBrowserName,
getHostname,
setHostname,
getCustomProfileName,
setCustomProfileName,
} from '../storage'
import { detectBrowser } from '../background/helpers'

Expand Down Expand Up @@ -34,6 +36,9 @@ async function saveOptions(e: SubmitEvent): Promise<void> {

const hostname = hostnameInput.value

const profileNameInput = document.querySelector<HTMLInputElement>('#profileName')
const profileName = profileNameInput?.value.trim() || ''

const form = e.target as HTMLFormElement
const button = form.querySelector<HTMLButtonElement>('button')
if (!button) return
Expand All @@ -44,6 +49,10 @@ async function saveOptions(e: SubmitEvent): Promise<void> {
try {
await setBrowserName(selectedBrowser)
await setHostname(hostname)

// Save custom profile name (empty string clears it)
await setCustomProfileName(profileName)

await reloadExtension()
button.textContent = 'Save'
button.classList.add('accept')
Expand Down Expand Up @@ -95,6 +104,13 @@ async function restoreOptions(): Promise<void> {
if (hostname !== undefined) {
hostnameInput.value = hostname
}

// Restore custom profile name
const customProfileName = await getCustomProfileName()
const profileNameInput = document.querySelector<HTMLInputElement>('#profileName')
if (profileNameInput && customProfileName) {
profileNameInput.value = customProfileName
}
} catch (error) {
console.error('Failed to restore options:', error)
}
Expand Down
46 changes: 46 additions & 0 deletions src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,49 @@ export const getHostname = (): Promise<Hostname | undefined> =>
.then((data: StorageData) => data.hostname as string | undefined)
export const setHostname = (hostname: Hostname) =>
browser.storage.local.set({ hostname })

type ProfileIdentifier = string
export const getProfileIdentifier = (): Promise<ProfileIdentifier | undefined> =>
browser.storage.local
.get('profileIdentifier')
.then((data: StorageData) => data.profileIdentifier as string | undefined)

export const setProfileIdentifier = (profileIdentifier: ProfileIdentifier) =>
browser.storage.local.set({ profileIdentifier })

export const generateProfileIdentifier = async (): Promise<ProfileIdentifier> => {
const existing = await getProfileIdentifier()
if (existing) {
return existing
}

// Generate a unique identifier for this profile/installation
const profileId = crypto.randomUUID()
await setProfileIdentifier(profileId)
return profileId
}

type CustomProfileName = string
export const getCustomProfileName = (): Promise<CustomProfileName | undefined> =>
browser.storage.local
.get('customProfileName')
.then((data: StorageData) => data.customProfileName as string | undefined)

export const setCustomProfileName = (customProfileName: CustomProfileName) => {
if (customProfileName.trim() === '') {
// Remove custom profile name if empty string is provided
return browser.storage.local.remove('customProfileName')
}
return browser.storage.local.set({ customProfileName })
}

export const getDisplayProfileName = async (): Promise<string> => {
const customName = await getCustomProfileName()
if (customName) {
return customName
}

// Fallback to a shortened version of the unique identifier
const profileId = await generateProfileIdentifier()
return `Profile-${profileId.slice(0, 8)}`
}
16 changes: 16 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineConfig } from 'vite'
import webExtension, { readJsonFile } from 'vite-plugin-web-extension'
import { copyFileSync, existsSync } from 'fs'
import { resolve } from 'path'

function generateManifest() {
const manifest = readJsonFile('src/manifest.json')
Expand All @@ -23,5 +25,19 @@ export default defineConfig({
additionalInputs: ['src/consent/index.html', 'src/consent/main.ts'],
browser: process.env.VITE_TARGET_BROWSER,
}),
// Custom plugin to copy logo file
{
name: 'copy-logo',
buildStart() {
const logoSrc = resolve('media/logo/logo-128.png')
const logoDest = resolve('build/logo-128.png')
if (existsSync(logoSrc)) {
copyFileSync(logoSrc, logoDest)
console.log('Copied logo-128.png to build directory')
} else {
console.warn('Logo file not found at media/logo/logo-128.png')
}
},
},
],
})