Finetuning Plugin behavior when not logged in

This commit is contained in:
2026-08-26 14:25:00 +02:00
parent f503dbaef2
commit 6f1fbaa5ea
11 changed files with 52 additions and 2 deletions
+6
View File
@@ -812,3 +812,9 @@ Don't forget to update the plugin to work with OTP.
### Assistant outcome ### Assistant outcome
Updated the Firefox extension settings login to accept and submit a six-digit one-time password. The backend supports TOTP setup, enable/disable confirmation, and OTP-enforced login, with the stored secret protected from profile responses. Updated the Firefox extension settings login to accept and submit a six-digit one-time password. The backend supports TOTP setup, enable/disable confirmation, and OTP-enforced login, with the stored secret protected from profile responses.
### User
When the user is not logged in, the plugin should display no form fields and warn them that they must log in, with a link to settings.
### Assistant outcome
The Firefox popup now hides capture fields by default for signed-out users, shows a localized sign-in warning, and provides an Open settings action. The form appears only after backend credentials and a valid session are available; expired sessions return to the warning state.
+1
View File
@@ -144,6 +144,7 @@
135. Correction: the feed header should have the sort and filter bar to the right of the LinkLog logo, compact and underneath the theme selector and menu. 135. Correction: the feed header should have the sort and filter bar to the right of the LinkLog logo, compact and underneath the theme selector and menu.
136. When a log entry is deleted then all mastodon posts are deleted too. 136. When a log entry is deleted then all mastodon posts are deleted too.
137. Don't forget to update the plugin to work with OTP. 137. Don't forget to update the plugin to work with OTP.
138. When the user is not logged in then the plugin should just display no form fields but warn the user that they have to log in with a link to settings.
## Future entries ## Future entries
Binary file not shown.
+2
View File
@@ -11,6 +11,8 @@
"newTagsPlaceholder": {"message": "#neuer-tag, #anderer-tag"}, "newTagsPlaceholder": {"message": "#neuer-tag, #anderer-tag"},
"saveLink": {"message": "Link speichern"}, "saveLink": {"message": "Link speichern"},
"settings": {"message": "Einstellungen"}, "settings": {"message": "Einstellungen"},
"authRequired": {"message": "Melde dich an, um LinkLog zu verwenden."},
"openSettings": {"message": "Einstellungen öffnen"},
"signOut": {"message": "Abmelden"}, "signOut": {"message": "Abmelden"},
"backendUrlLabel": {"message": "Backend-URL"}, "backendUrlLabel": {"message": "Backend-URL"},
"usernameLabel": {"message": "Benutzername"}, "usernameLabel": {"message": "Benutzername"},
@@ -35,6 +35,12 @@
"settings": { "settings": {
"message": "Settings" "message": "Settings"
}, },
"authRequired": {
"message": "Please sign in to use LinkLog."
},
"openSettings": {
"message": "Open settings"
},
"signOut": { "signOut": {
"message": "Sign out" "message": "Sign out"
}, },
+2
View File
@@ -11,6 +11,8 @@
"newTagsPlaceholder": {"message": "#nueva-etiqueta, #otra-etiqueta"}, "newTagsPlaceholder": {"message": "#nueva-etiqueta, #otra-etiqueta"},
"saveLink": {"message": "Guardar enlace"}, "saveLink": {"message": "Guardar enlace"},
"settings": {"message": "Configuración"}, "settings": {"message": "Configuración"},
"authRequired": {"message": "Inicia sesión para usar LinkLog."},
"openSettings": {"message": "Abrir configuración"},
"signOut": {"message": "Cerrar sesión"}, "signOut": {"message": "Cerrar sesión"},
"backendUrlLabel": {"message": "URL del servidor"}, "backendUrlLabel": {"message": "URL del servidor"},
"usernameLabel": {"message": "Nombre de usuario"}, "usernameLabel": {"message": "Nombre de usuario"},
+2
View File
@@ -11,6 +11,8 @@
"newTagsPlaceholder": {"message": "#nouvelle-étiquette, #autre-étiquette"}, "newTagsPlaceholder": {"message": "#nouvelle-étiquette, #autre-étiquette"},
"saveLink": {"message": "Enregistrer le lien"}, "saveLink": {"message": "Enregistrer le lien"},
"settings": {"message": "Paramètres"}, "settings": {"message": "Paramètres"},
"authRequired": {"message": "Connectez-vous pour utiliser LinkLog."},
"openSettings": {"message": "Ouvrir les paramètres"},
"signOut": {"message": "Se déconnecter"}, "signOut": {"message": "Se déconnecter"},
"backendUrlLabel": {"message": "URL du serveur"}, "backendUrlLabel": {"message": "URL du serveur"},
"usernameLabel": {"message": "Nom dutilisateur"}, "usernameLabel": {"message": "Nom dutilisateur"},
+2
View File
@@ -11,6 +11,8 @@
"newTagsPlaceholder": {"message": "#nieuwe-tag, #andere-tag"}, "newTagsPlaceholder": {"message": "#nieuwe-tag, #andere-tag"},
"saveLink": {"message": "Koppeling opslaan"}, "saveLink": {"message": "Koppeling opslaan"},
"settings": {"message": "Instellingen"}, "settings": {"message": "Instellingen"},
"authRequired": {"message": "Log in om LinkLog te gebruiken."},
"openSettings": {"message": "Instellingen openen"},
"signOut": {"message": "Uitloggen"}, "signOut": {"message": "Uitloggen"},
"backendUrlLabel": {"message": "Backend-URL"}, "backendUrlLabel": {"message": "Backend-URL"},
"usernameLabel": {"message": "Gebruikersnaam"}, "usernameLabel": {"message": "Gebruikersnaam"},
+9
View File
@@ -149,6 +149,15 @@ button {
color: #f38ba8; color: #f38ba8;
} }
#auth-warning {
display: grid;
gap: 8px;
}
#auth-warning button {
width: auto;
}
.hidden { .hidden {
display: none; display: none;
} }
+5 -1
View File
@@ -15,8 +15,12 @@
</header> </header>
<div id="status" class="status hidden" aria-live="polite"></div> <div id="status" class="status hidden" aria-live="polite"></div>
<div id="auth-warning" class="status error" aria-live="polite">
<span data-i18n="authRequired">Please sign in to use LinkLog.</span>
<button type="button" id="warning-settings" class="secondary" data-i18n="openSettings">Open settings</button>
</div>
<form id="link-form"> <form id="link-form" class="hidden">
<label> <label>
<span data-i18n="titleLabel">Title</span> <span data-i18n="titleLabel">Title</span>
<input id="title" name="title" type="text" /> <input id="title" name="title" type="text" />
+17 -1
View File
@@ -10,6 +10,8 @@ const openSettingsButton = document.getElementById('open-settings');
const existingTags = document.getElementById('existing-tags'); const existingTags = document.getElementById('existing-tags');
const newTagsInput = document.getElementById('new-tags'); const newTagsInput = document.getElementById('new-tags');
const feedLink = document.getElementById('feed-link'); const feedLink = document.getElementById('feed-link');
const authWarning = document.getElementById('auth-warning');
const warningSettingsButton = document.getElementById('warning-settings');
const t = window.linklogI18n; const t = window.linklogI18n;
@@ -29,6 +31,16 @@ async function getSettings() {
return result; return result;
} }
function showSignedOutState() {
form.classList.add('hidden');
authWarning.classList.remove('hidden');
}
function showSignedInState() {
authWarning.classList.add('hidden');
form.classList.remove('hidden');
}
async function updateFeedLink() { async function updateFeedLink() {
const settings = await browser.storage.local.get(['backendUrl', 'username', 'accessToken']); const settings = await browser.storage.local.get(['backendUrl', 'username', 'accessToken']);
if (!settings.backendUrl || !settings.username || !settings.accessToken) return; if (!settings.backendUrl || !settings.username || !settings.accessToken) return;
@@ -44,13 +56,15 @@ async function updateFeedLink() {
async function loadExistingTags() { async function loadExistingTags() {
const settings = await getSettings(); const settings = await getSettings();
if (!settings.backendUrl || !settings.accessToken) { if (!settings.backendUrl || !settings.accessToken) {
existingTags.textContent = t('signInToSelectTags'); showSignedOutState();
return; return;
} }
showSignedInState();
const response = await fetch(`${settings.backendUrl}/api/tags`, { const response = await fetch(`${settings.backendUrl}/api/tags`, {
headers: {'Authorization': `Bearer ${settings.accessToken}`}, headers: {'Authorization': `Bearer ${settings.accessToken}`},
}); });
if (!response.ok) { if (!response.ok) {
if (response.status === 401) showSignedOutState();
existingTags.textContent = t('loadTagsFailed'); existingTags.textContent = t('loadTagsFailed');
return; return;
} }
@@ -127,6 +141,7 @@ async function handleSubmit(event) {
}); });
if (response.status === 401) { if (response.status === 401) {
showSignedOutState();
setStatus(t('sessionExpired'), true); setStatus(t('sessionExpired'), true);
browser.runtime.openOptionsPage(); browser.runtime.openOptionsPage();
return; return;
@@ -143,6 +158,7 @@ async function handleSubmit(event) {
} }
openSettingsButton.addEventListener('click', () => browser.runtime.openOptionsPage()); openSettingsButton.addEventListener('click', () => browser.runtime.openOptionsPage());
warningSettingsButton.addEventListener('click', () => browser.runtime.openOptionsPage());
form.addEventListener('submit', handleSubmit); form.addEventListener('submit', handleSubmit);
populateCurrentTab(); populateCurrentTab();
loadExistingTags(); loadExistingTags();