mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-05-11 17:03:33 -04:00
Add vault upgrade check to autofill popup (#957)
This commit is contained in:
committed by
Leendert de Borst
parent
3e82c6e5d0
commit
afe2ba52b5
@@ -14,9 +14,9 @@ import { VaultUploadResponse as messageVaultUploadResponse } from '@/utils/types
|
||||
import { WebApiService } from '@/utils/WebApiService';
|
||||
|
||||
/**
|
||||
* Check if the user is logged in and if the vault is locked.
|
||||
* Check if the user is logged in and if the vault is locked, and also check for pending migrations.
|
||||
*/
|
||||
export async function handleCheckAuthStatus() : Promise<{ isLoggedIn: boolean, isVaultLocked: boolean }> {
|
||||
export async function handleCheckAuthStatus() : Promise<{ isLoggedIn: boolean, isVaultLocked: boolean, hasPendingMigrations: boolean, error?: string }> {
|
||||
const username = await storage.getItem('local:username');
|
||||
const accessToken = await storage.getItem('local:accessToken');
|
||||
const vaultData = await storage.getItem('session:encryptedVault');
|
||||
@@ -24,10 +24,42 @@ export async function handleCheckAuthStatus() : Promise<{ isLoggedIn: boolean, i
|
||||
const isLoggedIn = username !== null && accessToken !== null;
|
||||
const isVaultLocked = isLoggedIn && vaultData === null;
|
||||
|
||||
return {
|
||||
isLoggedIn,
|
||||
isVaultLocked
|
||||
};
|
||||
// If vault is locked, we can't check for pending migrations
|
||||
if (isVaultLocked) {
|
||||
return {
|
||||
isLoggedIn,
|
||||
isVaultLocked,
|
||||
hasPendingMigrations: false
|
||||
};
|
||||
}
|
||||
|
||||
// If not logged in, no need to check migrations
|
||||
if (!isLoggedIn) {
|
||||
return {
|
||||
isLoggedIn,
|
||||
isVaultLocked,
|
||||
hasPendingMigrations: false
|
||||
};
|
||||
}
|
||||
|
||||
// Vault is unlocked, check for pending migrations
|
||||
try {
|
||||
const sqliteClient = await createVaultSqliteClient();
|
||||
const hasPendingMigrations = await sqliteClient.hasPendingMigrations();
|
||||
return {
|
||||
isLoggedIn,
|
||||
isVaultLocked,
|
||||
hasPendingMigrations
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error checking pending migrations:', error);
|
||||
return {
|
||||
isLoggedIn,
|
||||
isVaultLocked,
|
||||
hasPendingMigrations: false,
|
||||
error: error instanceof Error ? error.message : 'An unknown error occurred'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@ import '@/entrypoints/contentScript/style.css';
|
||||
import { onMessage } from "webext-bridge/content-script";
|
||||
|
||||
import { injectIcon, popupDebounceTimeHasPassed, validateInputField } from '@/entrypoints/contentScript/Form';
|
||||
import { isAutoShowPopupEnabled, openAutofillPopup, removeExistingPopup } from '@/entrypoints/contentScript/Popup';
|
||||
import { isAutoShowPopupEnabled, openAutofillPopup, removeExistingPopup, createUpgradeRequiredPopup } from '@/entrypoints/contentScript/Popup';
|
||||
|
||||
import { FormDetector } from '@/utils/formDetector/FormDetector';
|
||||
import { BoolResponse as messageBoolResponse } from '@/utils/types/messaging/BoolResponse';
|
||||
@@ -69,7 +69,7 @@ export default defineContentScript({
|
||||
|
||||
// Only show popup if debounce time has passed
|
||||
if (popupDebounceTimeHasPassed()) {
|
||||
openAutofillPopup(inputElement, container);
|
||||
await showPopupWithAuthCheck(inputElement, container);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,48 @@ export default defineContentScript({
|
||||
|
||||
if (canShowPopup) {
|
||||
injectIcon(inputElement, container);
|
||||
await showPopupWithAuthCheck(inputElement, container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show popup with auth check.
|
||||
*/
|
||||
async function showPopupWithAuthCheck(inputElement: HTMLInputElement, container: HTMLElement) : Promise<void> {
|
||||
try {
|
||||
// Check auth status and pending migrations in a single call
|
||||
const { sendMessage } = await import('webext-bridge/content-script');
|
||||
const authStatus = await sendMessage('CHECK_AUTH_STATUS', {}, 'background') as {
|
||||
isLoggedIn: boolean,
|
||||
isVaultLocked: boolean,
|
||||
hasPendingMigrations: boolean,
|
||||
error?: string
|
||||
};
|
||||
|
||||
if (authStatus.isVaultLocked) {
|
||||
// Vault is locked, show vault locked popup
|
||||
const { createVaultLockedPopup } = await import('@/entrypoints/contentScript/Popup');
|
||||
createVaultLockedPopup(inputElement, container);
|
||||
return;
|
||||
}
|
||||
|
||||
if (authStatus.hasPendingMigrations) {
|
||||
// Show upgrade required popup
|
||||
createUpgradeRequiredPopup(inputElement, container, 'Vault upgrade required.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (authStatus.error) {
|
||||
// Show upgrade required popup for version-related errors
|
||||
createUpgradeRequiredPopup(inputElement, container, authStatus.error);
|
||||
return;
|
||||
}
|
||||
|
||||
// No upgrade required, show normal autofill popup
|
||||
openAutofillPopup(inputElement, container);
|
||||
} catch (error) {
|
||||
console.error('Error checking vault status:', error);
|
||||
// Fall back to normal autofill popup if check fails
|
||||
openAutofillPopup(inputElement, container);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1462,3 +1462,92 @@ function addReliableClickHandler(element: HTMLElement, handler: (e: Event) => vo
|
||||
isMouseDown = false;
|
||||
}, { capture: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create upgrade required popup.
|
||||
*/
|
||||
export function createUpgradeRequiredPopup(input: HTMLInputElement, rootContainer: HTMLElement, errorMessage: string): void {
|
||||
/**
|
||||
* Handle upgrade click.
|
||||
*/
|
||||
const handleUpgradeClick = () : void => {
|
||||
sendMessage('OPEN_POPUP', {}, 'background');
|
||||
removeExistingPopup(rootContainer);
|
||||
}
|
||||
|
||||
const popup = createBasePopup(input, rootContainer);
|
||||
popup.classList.add('av-upgrade-required');
|
||||
|
||||
// Create container for message and button
|
||||
const container = document.createElement('div');
|
||||
container.className = 'av-upgrade-required-container';
|
||||
|
||||
// Make the entire container clickable
|
||||
addReliableClickHandler(container, handleUpgradeClick);
|
||||
container.style.cursor = 'pointer';
|
||||
|
||||
// Add message
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.className = 'av-upgrade-required-message';
|
||||
messageElement.textContent = errorMessage;
|
||||
container.appendChild(messageElement);
|
||||
|
||||
// Add upgrade button with SVG icon
|
||||
const button = document.createElement('button');
|
||||
button.title = 'Open AliasVault to upgrade';
|
||||
button.className = 'av-upgrade-required-button';
|
||||
button.innerHTML = `
|
||||
<svg class="av-icon-upgrade" viewBox="0 0 24 24">
|
||||
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"></path>
|
||||
</svg>
|
||||
`;
|
||||
container.appendChild(button);
|
||||
|
||||
// Add the container to the popup
|
||||
popup.appendChild(container);
|
||||
|
||||
// Add close button as a separate element positioned to the right
|
||||
const closeButton = document.createElement('button');
|
||||
closeButton.className = 'av-button av-button-close av-upgrade-required-close';
|
||||
closeButton.title = 'Dismiss popup';
|
||||
closeButton.innerHTML = `
|
||||
<svg class="av-icon" viewBox="0 0 24 24">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
// Position the close button to the right of the container
|
||||
closeButton.style.position = 'absolute';
|
||||
closeButton.style.right = '8px';
|
||||
closeButton.style.top = '50%';
|
||||
closeButton.style.transform = 'translateY(-50%)';
|
||||
|
||||
// Handle close button click
|
||||
addReliableClickHandler(closeButton, (e) => {
|
||||
e.stopPropagation(); // Prevent opening the upgrade popup
|
||||
removeExistingPopup(rootContainer);
|
||||
});
|
||||
|
||||
popup.appendChild(closeButton);
|
||||
|
||||
/**
|
||||
* Add event listener to document to close popup when clicking outside.
|
||||
*/
|
||||
const handleClickOutside = (event: MouseEvent): void => {
|
||||
const target = event.target as Node;
|
||||
const targetElement = event.target as HTMLElement;
|
||||
|
||||
// Check if the click is outside the popup and outside the shadow UI
|
||||
if (popup && !popup.contains(target) && !input.contains(target) && targetElement.tagName !== 'ALIASVAULT-UI') {
|
||||
removeExistingPopup(rootContainer);
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
}, 100);
|
||||
|
||||
rootContainer.appendChild(popup);
|
||||
}
|
||||
|
||||
@@ -299,6 +299,71 @@ body {
|
||||
border: 1px solid #6f6f6f;
|
||||
}
|
||||
|
||||
/* Upgrade Required Popup */
|
||||
.av-upgrade-required {
|
||||
padding: 12px 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.av-upgrade-required:hover {
|
||||
background-color: #374151;
|
||||
}
|
||||
|
||||
.av-upgrade-required-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 32px;
|
||||
width: 100%;
|
||||
transition: background-color 0.2s ease;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.av-upgrade-required-message {
|
||||
color: #d1d5db;
|
||||
font-size: 14px;
|
||||
flex-grow: 1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
|
||||
.av-upgrade-required-button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
padding-right: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #f59e0b;
|
||||
border-radius: 4px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.av-upgrade-required-close {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
padding: 4px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
border: 1px solid #6f6f6f;
|
||||
}
|
||||
|
||||
.av-icon-upgrade {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
/* Create Name Popup */
|
||||
.av-create-popup-overlay {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user