Add dynamic channel selector feedback with pulse highlight
- Channel select shows contextual info: Auto (server key), Public (no key), Custom (hidden) - Gold pulse highlight on custom channel input when selected - Smooth 0.4s animation with subtle glow effect - Updated encode.html and decode.html with data-fingerprint attributes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -765,18 +765,43 @@ const Stegasoo = {
|
|||||||
const customInputId = config.customInputId || 'channelCustomInput';
|
const customInputId = config.customInputId || 'channelCustomInput';
|
||||||
const keyInputId = config.keyInputId || 'channelKeyInput';
|
const keyInputId = config.keyInputId || 'channelKeyInput';
|
||||||
const generateBtnId = config.generateBtnId;
|
const generateBtnId = config.generateBtnId;
|
||||||
|
const serverInfoId = config.serverInfoId || 'channelServerInfo';
|
||||||
|
|
||||||
const select = document.getElementById(selectId);
|
const select = document.getElementById(selectId);
|
||||||
const customInput = document.getElementById(customInputId);
|
const customInput = document.getElementById(customInputId);
|
||||||
const keyInput = document.getElementById(keyInputId);
|
const keyInput = document.getElementById(keyInputId);
|
||||||
const generateBtn = generateBtnId ? document.getElementById(generateBtnId) : null;
|
const generateBtn = generateBtnId ? document.getElementById(generateBtnId) : null;
|
||||||
|
const serverInfo = document.getElementById(serverInfoId);
|
||||||
|
|
||||||
// Show/hide custom input based on selection
|
// Show/hide custom input and server info based on selection
|
||||||
const updateVisibility = () => {
|
const updateVisibility = () => {
|
||||||
const isCustom = select?.value === 'custom';
|
const value = select?.value;
|
||||||
|
const isCustom = value === 'custom';
|
||||||
|
const isPublic = value === 'none';
|
||||||
|
const isAuto = value === 'auto';
|
||||||
|
|
||||||
|
// Custom input visibility
|
||||||
customInput?.classList.toggle('d-none', !isCustom);
|
customInput?.classList.toggle('d-none', !isCustom);
|
||||||
if (isCustom && keyInput) {
|
if (isCustom && keyInput) {
|
||||||
keyInput.focus();
|
keyInput.focus();
|
||||||
|
// Pulse highlight effect
|
||||||
|
customInput?.classList.add('channel-highlight');
|
||||||
|
setTimeout(() => customInput?.classList.remove('channel-highlight'), 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server info: show for auto, hide for custom, show "no key" for public
|
||||||
|
if (serverInfo) {
|
||||||
|
if (isAuto) {
|
||||||
|
serverInfo.innerHTML = '<i class="bi bi-shield-lock me-1"></i>Server: <code>' + (serverInfo.dataset.fingerprint || '••••-••••-···-••••-••••') + '</code>';
|
||||||
|
serverInfo.className = 'small text-success mt-2';
|
||||||
|
serverInfo.classList.remove('d-none');
|
||||||
|
} else if (isPublic) {
|
||||||
|
serverInfo.innerHTML = '<i class="bi bi-globe me-1"></i>No channel key will be used';
|
||||||
|
serverInfo.className = 'small text-muted mt-2';
|
||||||
|
serverInfo.classList.remove('d-none');
|
||||||
|
} else {
|
||||||
|
serverInfo.classList.add('d-none');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -912,7 +937,8 @@ const Stegasoo = {
|
|||||||
this.initChannelKey({
|
this.initChannelKey({
|
||||||
selectId: 'channelSelectDec',
|
selectId: 'channelSelectDec',
|
||||||
customInputId: 'channelCustomInputDec',
|
customInputId: 'channelCustomInputDec',
|
||||||
keyInputId: 'channelKeyInputDec'
|
keyInputId: 'channelKeyInputDec',
|
||||||
|
serverInfoId: 'channelServerInfoDec'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form submission with channel key validation and mode display
|
// Form submission with channel key validation and mode display
|
||||||
|
|||||||
@@ -161,6 +161,17 @@ body {
|
|||||||
.btn-group .btn-outline-secondary:hover {
|
.btn-group .btn-outline-secondary:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.08);
|
background-color: rgba(255, 255, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Channel key highlight pulse */
|
||||||
|
.channel-highlight {
|
||||||
|
animation: channel-pulse 0.4s ease;
|
||||||
|
}
|
||||||
|
@keyframes channel-pulse {
|
||||||
|
0% { box-shadow: 0 0 0 0 rgba(254, 232, 98, 0); }
|
||||||
|
20% { box-shadow: 0 0 9px 1px rgba(254, 232, 98, 0.19); }
|
||||||
|
40% { box-shadow: 0 0 9px 1px rgba(254, 232, 98, 0.19); }
|
||||||
|
100% { box-shadow: 0 0 0 0 rgba(254, 232, 98, 0); }
|
||||||
|
}
|
||||||
.btn-group .btn-outline-primary:first-of-type,
|
.btn-group .btn-outline-primary:first-of-type,
|
||||||
.btn-group .btn-outline-secondary:first-of-type {
|
.btn-group .btn-outline-secondary:first-of-type {
|
||||||
color: #6b4d8a;
|
color: #6b4d8a;
|
||||||
|
|||||||
@@ -362,15 +362,15 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- Server channel indicator (compact) -->
|
<!-- Server channel indicator (compact) -->
|
||||||
|
<div class="small text-success mt-2 {% if not channel_configured %}d-none{% endif %}" id="channelServerInfoDec" data-fingerprint="{{ channel_fingerprint[:4] }}-••••-···-••••-{{ channel_fingerprint[-4:] if channel_fingerprint else '' }}">
|
||||||
{% if channel_configured %}
|
{% if channel_configured %}
|
||||||
<div class="small text-success mt-2">
|
|
||||||
<i class="bi bi-shield-lock me-1"></i>
|
<i class="bi bi-shield-lock me-1"></i>
|
||||||
Server: <code>{{ channel_fingerprint[:4] }}-••••-···-••••-{{ channel_fingerprint[-4:] }}</code>
|
Server: <code>{{ channel_fingerprint[:4] }}-••••-···-••••-{{ channel_fingerprint[-4:] }}</code>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Custom Channel Key Input (shown when Custom selected) -->
|
<!-- Custom Channel Key Input (shown when Custom selected) -->
|
||||||
<div class="mb-4 d-none" id="channelCustomInputDec">
|
<div class="mb-4 d-none" id="channelCustomInputDec">
|
||||||
|
|||||||
@@ -429,15 +429,15 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- Server channel indicator (compact) -->
|
<!-- Server channel indicator (compact) -->
|
||||||
|
<div class="small text-success mt-2 {% if not channel_configured %}d-none{% endif %}" id="channelServerInfo" data-fingerprint="{{ channel_fingerprint[:4] }}-••••-···-••••-{{ channel_fingerprint[-4:] if channel_fingerprint else '' }}">
|
||||||
{% if channel_configured %}
|
{% if channel_configured %}
|
||||||
<div class="small text-success mt-2" id="channelServerInfo">
|
|
||||||
<i class="bi bi-shield-lock me-1"></i>
|
<i class="bi bi-shield-lock me-1"></i>
|
||||||
Server: <code>{{ channel_fingerprint[:4] }}-••••-···-••••-{{ channel_fingerprint[-4:] }}</code>
|
Server: <code>{{ channel_fingerprint[:4] }}-••••-···-••••-{{ channel_fingerprint[-4:] }}</code>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Custom Channel Key Input (shown when Custom selected) -->
|
<!-- Custom Channel Key Input (shown when Custom selected) -->
|
||||||
<div class="mb-4 d-none" id="channelCustomInput">
|
<div class="mb-4 d-none" id="channelCustomInput">
|
||||||
|
|||||||
Reference in New Issue
Block a user