Add smooth account editor transitions with immediate input release, keep the cursor visible in development and production windows, align host option descriptions, and ensure localized settings search placeholders fit at narrow widths. Bump the application to v2.1.22 and extend hidden Electron regression coverage.
This commit is contained in:
+44
-7
@@ -5987,17 +5987,17 @@ function _buildHosterSettingsHtml(name) {
|
||||
<input id="${fieldPrefix}-max-size" type="number" class="hs-input" data-hoster="${name}" data-hs="maxSizeMb" value="${hs.maxSizeMb ?? 0}" min="0">
|
||||
<span class="hint">0 = unbegrenzt</span>
|
||||
</div>
|
||||
<div class="settings-row">
|
||||
<div class="settings-row account-hoster-option-row">
|
||||
<label for="${fieldPrefix}-log">Links in Log schreiben</label>
|
||||
<input id="${fieldPrefix}-log" type="checkbox" class="hs-input" data-hoster="${name}" data-hs="logToFile" ${hs.logToFile !== false ? 'checked' : ''}>
|
||||
<span class="hint">Erfolgreiche Links in fileuploader.log.</span>
|
||||
</div>
|
||||
<div class="settings-row">
|
||||
<div class="settings-row account-hoster-option-row">
|
||||
<label for="${fieldPrefix}-rotate">Accounts rotieren</label>
|
||||
<input id="${fieldPrefix}-rotate" type="checkbox" class="hs-input" data-hoster="${name}" data-hs="rotateAccounts" ${hs.rotateAccounts === true ? 'checked' : ''}>
|
||||
<span class="hint">Verteilt die Dateien reihum auf alle aktiven Accounts dieses Hosters (Datei 1 → Account 1, Datei 2 → Account 2 …). Hält z. B. byse-Accounts aktiv. Nur ein Account = kein Effekt.</span>
|
||||
<span class="hint">Verteilt Dateien abwechselnd auf alle aktiven Accounts dieses Hosters. Bei nur einem Account hat die Option keinen Effekt.</span>
|
||||
</div>
|
||||
<div class="settings-row">
|
||||
<div class="settings-row account-hoster-option-row">
|
||||
<label for="${fieldPrefix}-size-memo">Größen-Limit merken</label>
|
||||
<input id="${fieldPrefix}-size-memo" type="checkbox" class="hs-input" data-hoster="${name}" data-hs="sizeMemoEnabled" ${hs.sizeMemoEnabled !== false ? 'checked' : ''}>
|
||||
<span class="hint">Überspringt nach zwei verdächtigen Ablehnungen auf einem Account größere Dateien dort vorab ("Bekanntes Größen-Limit"). Abschalten = jede Datei wird immer wirklich versucht.</span>
|
||||
@@ -6353,7 +6353,7 @@ function getCredsFieldsHtml(authType, account, hoster) {
|
||||
<div class="settings-row">
|
||||
<label for="accField_password">Passwort</label>
|
||||
<input type="password" class="key-input" id="accField_password" name="password" autocomplete="current-password" value="${escapeAttr(account.password || '')}" placeholder="Passwort">
|
||||
<button class="toggle-vis" type="button" title="Passwort anzeigen" aria-label="Passwort anzeigen" aria-pressed="false">👁</button>
|
||||
<button class="toggle-vis" type="button" title="Passwort anzeigen" aria-label="Passwort anzeigen" aria-pressed="false">👁️</button>
|
||||
</div>`;
|
||||
}
|
||||
// API key
|
||||
@@ -6361,7 +6361,7 @@ function getCredsFieldsHtml(authType, account, hoster) {
|
||||
<div class="settings-row">
|
||||
<label for="accField_apiKey">API-Key</label>
|
||||
<input type="password" class="key-input" id="accField_apiKey" name="apiKey" autocomplete="off" spellcheck="false" value="${escapeAttr(account.apiKey || '')}" placeholder="API-Key">
|
||||
<button class="toggle-vis" type="button" title="API-Key anzeigen" aria-label="API-Key anzeigen" aria-pressed="false">👁</button>
|
||||
<button class="toggle-vis" type="button" title="API-Key anzeigen" aria-label="API-Key anzeigen" aria-pressed="false">👁️</button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -6429,13 +6429,50 @@ function openAccountModal(editAccountId) {
|
||||
onEscape: closeAccountModal,
|
||||
onBackdrop: closeAccountModal
|
||||
});
|
||||
_openAccountModalMotion(modal);
|
||||
}
|
||||
|
||||
let _accountModalMotionToken = 0;
|
||||
|
||||
function _openAccountModalMotion(modal) {
|
||||
const card = modal.querySelector('.modal-card');
|
||||
const token = ++_accountModalMotionToken;
|
||||
modal.classList.remove('account-modal-opening', 'account-modal-closing');
|
||||
if (!card) return;
|
||||
void card.offsetHeight;
|
||||
modal.classList.add('account-modal-opening');
|
||||
const finish = event => {
|
||||
if (event && event.target !== card) return;
|
||||
card.removeEventListener('animationend', finish);
|
||||
if (Object.is(token, _accountModalMotionToken)) modal.classList.remove('account-modal-opening');
|
||||
};
|
||||
card.addEventListener('animationend', finish);
|
||||
window.setTimeout(() => finish(), 440);
|
||||
}
|
||||
|
||||
function closeAccountModal() {
|
||||
modalController.close('accountModal', { fallbackFocus: '#addAccountBtn' });
|
||||
const modal = document.getElementById('accountModal');
|
||||
if (!modalController.isOpen(modal) || modal.classList.contains('account-modal-closing')) return;
|
||||
const card = modal.querySelector('.modal-card');
|
||||
const token = ++_accountModalMotionToken;
|
||||
modal.classList.remove('account-modal-opening', 'account-modal-closing');
|
||||
if (card) void card.offsetHeight;
|
||||
modalController.close(modal, { fallbackFocus: '#addAccountBtn' });
|
||||
modal.style.display = 'flex';
|
||||
modal.inert = true;
|
||||
modal.classList.add('account-modal-closing');
|
||||
_hideOtpField();
|
||||
editingAccountId = null;
|
||||
_resetAccountModalState();
|
||||
const finish = event => {
|
||||
if (event && event.target !== card) return;
|
||||
if (card) card.removeEventListener('animationend', finish);
|
||||
if (!Object.is(token, _accountModalMotionToken)) return;
|
||||
modal.classList.remove('account-modal-closing');
|
||||
modal.style.display = 'none';
|
||||
};
|
||||
if (card) card.addEventListener('animationend', finish);
|
||||
window.setTimeout(() => finish(), 380);
|
||||
}
|
||||
|
||||
function openDeleteAccountModal(accountId) {
|
||||
|
||||
+1
-1
@@ -237,7 +237,7 @@
|
||||
['Hoster-Einstellungen', 'Host settings'],
|
||||
['Upload-Einstellungen', 'Upload settings'],
|
||||
['Erfolgreiche Links in fileuploader.log.', 'Successful links in fileuploader.log.'],
|
||||
['Verteilt die Dateien reihum auf alle aktiven Accounts dieses Hosters (Datei 1 → Account 1, Datei 2 → Account 2 …). Hält z. B. byse-Accounts aktiv. Nur ein Account = kein Effekt.', 'Distributes files across all active accounts for this host in round-robin order (file 1 → account 1, file 2 → account 2, and so on). Keeps accounts such as byse active. Has no effect with only one account.'],
|
||||
['Verteilt Dateien abwechselnd auf alle aktiven Accounts dieses Hosters. Bei nur einem Account hat die Option keinen Effekt.', 'Distributes files alternately across all active accounts for this host. The option has no effect with only one account.'],
|
||||
['Größen-Limit merken', 'Remember size limit'],
|
||||
['Überspringt nach zwei verdächtigen Ablehnungen auf einem Account größere Dateien dort vorab ("Bekanntes Größen-Limit"). Abschalten = jede Datei wird immer wirklich versucht.', 'After two suspicious rejections on an account, larger files are skipped there in advance ("Known size limit"). When disabled, every file is always attempted.'],
|
||||
['Einstellungen einzelner Hoster', 'Settings for individual hosts'],
|
||||
|
||||
+66
-1
@@ -29,6 +29,7 @@
|
||||
body {
|
||||
font-family: 'Aptos', 'Segoe UI Variable Text', 'Bahnschrift', sans-serif;
|
||||
background: var(--bg-primary);
|
||||
cursor: default;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
color: var(--text);
|
||||
@@ -1287,6 +1288,29 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; }
|
||||
.account-hoster-settings-header .panel-arrow { font-size: 10px; color: var(--text-dim); }
|
||||
.account-hoster-settings-body-inner { padding: 4px 12px 10px; }
|
||||
|
||||
.account-hoster-settings-body-inner .account-hoster-option-row {
|
||||
grid-column: 1 / -1;
|
||||
display: grid;
|
||||
grid-template-columns: 150px minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
column-gap: 12px;
|
||||
}
|
||||
|
||||
.account-hoster-settings-body-inner .account-hoster-option-row label {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.account-hoster-settings-body-inner .account-hoster-option-row .hint {
|
||||
grid-column: 2;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.account-hoster-settings-body-inner .account-hoster-option-row input[type="checkbox"] {
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.settings-hoster-pointer {
|
||||
margin-top: 12px;
|
||||
padding: 10px 14px;
|
||||
@@ -3456,7 +3480,7 @@ input[type="checkbox"] {
|
||||
}
|
||||
|
||||
#settingsSearchInput {
|
||||
font-size: 13px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.settings-nav-button {
|
||||
@@ -3753,6 +3777,47 @@ input[type="checkbox"] {
|
||||
box-shadow: 0 24px 64px rgba(0, 0, 0, .48);
|
||||
}
|
||||
|
||||
#accountModal.account-modal-opening {
|
||||
animation: account-modal-dim-in 360ms cubic-bezier(.16, 1, .3, 1) both;
|
||||
}
|
||||
|
||||
#accountModal.account-modal-opening > .modal-card {
|
||||
transform-origin: top center;
|
||||
animation: account-modal-unfold 360ms cubic-bezier(.16, 1, .3, 1) both;
|
||||
}
|
||||
|
||||
#accountModal.account-modal-closing {
|
||||
pointer-events: none;
|
||||
animation: account-modal-dim-out 300ms cubic-bezier(.4, 0, .2, 1) both;
|
||||
}
|
||||
|
||||
#accountModal.account-modal-closing > .modal-card {
|
||||
transform-origin: top center;
|
||||
animation: account-modal-fold 300ms cubic-bezier(.4, 0, .2, 1) both;
|
||||
}
|
||||
|
||||
@keyframes account-modal-dim-in {
|
||||
from { background: rgba(0, 0, 0, 0); }
|
||||
to { background: rgba(0, 0, 0, .6); }
|
||||
}
|
||||
|
||||
@keyframes account-modal-dim-out {
|
||||
from { background: rgba(0, 0, 0, .6); }
|
||||
to { background: rgba(0, 0, 0, 0); }
|
||||
}
|
||||
|
||||
@keyframes account-modal-unfold {
|
||||
0% { opacity: 0; clip-path: inset(0 0 18% 0 round 12px); transform: translateY(-16px) scale(.985); }
|
||||
55% { opacity: .96; }
|
||||
100% { opacity: 1; clip-path: inset(0 round 12px); transform: translateY(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes account-modal-fold {
|
||||
0% { opacity: 1; clip-path: inset(0 round 12px); transform: translateY(0) scale(1); }
|
||||
45% { opacity: .9; }
|
||||
100% { opacity: 0; clip-path: inset(0 0 18% 0 round 12px); transform: translateY(-16px) scale(.985); }
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-footer {
|
||||
padding: 16px 18px;
|
||||
|
||||
Reference in New Issue
Block a user