feat(messages): show pin icon on pinned messages in chat, click to unpin
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-03-27 15:15:59 +01:00
parent 3259ae3c05
commit f3fc7060ee
3 changed files with 43 additions and 3 deletions

View File

@ -966,6 +966,19 @@
transform: none;
}
/* --- Pin indicator on message --- */
.pin-indicator {
display: inline-block;
cursor: pointer;
font-size: 13px;
opacity: 0.5;
margin-top: 2px;
transition: opacity 0.15s;
}
.pin-indicator:hover {
opacity: 1;
}
.input-hint {
font-size: 12px;
color: var(--conv-text-secondary, #605e5c);

View File

@ -33,6 +33,7 @@
presenceInterval: null,
typingTimeout: null,
reconnectDelay: 1000,
pinnedMessageIds: [], // IDs of pinned messages in current conversation
isMobile: window.innerWidth <= 768,
};
@ -397,8 +398,16 @@
}
}
// Pinned bar
// Pinned bar — load actual pin IDs
Pins.updateBar(details.pins_count || 0);
try {
var pinsData = await api('/api/conversations/' + conversationId + '/pins');
var pinsList = Array.isArray(pinsData) ? pinsData : (pinsData.pins || []);
state.pinnedMessageIds = pinsList.map(function (p) { return p.message_id; });
Pins.updateBar(pinsList.length);
} catch (_) {
state.pinnedMessageIds = [];
}
} catch (e) {
// silently ignore detail load errors
}
@ -569,6 +578,24 @@
bubble.appendChild(Reactions.renderPills(msg));
}
// Pinned indicator
if (state.pinnedMessageIds.indexOf(msg.id) >= 0) {
var pinIndicator = el('div', 'pin-indicator');
pinIndicator.innerHTML = '📌';
pinIndicator.title = 'Przypięta — kliknij aby odpiąć';
pinIndicator.addEventListener('click', function (e) {
e.stopPropagation();
api('/api/messages/' + msg.id + '/pin', 'DELETE')
.then(function () {
state.pinnedMessageIds = state.pinnedMessageIds.filter(function (id) { return id !== msg.id; });
Pins.updateBar(state.pinnedMessageIds.length);
pinIndicator.remove();
})
.catch(function () {});
});
bubble.appendChild(pinIndicator);
}
row.appendChild(bubble);
// Context menu triggers

View File

@ -5,7 +5,7 @@
{% block head_extra %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/quill.snow.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/conversations.css') }}?v=3">
<link rel="stylesheet" href="{{ url_for('static', filename='css/conversations.css') }}?v=4">
<script src="{{ url_for('static', filename='js/vendor/quill.js') }}"></script>
<style>
footer { display: none !important; }
@ -245,7 +245,7 @@ window.__CSRF_TOKEN__ = '{{ csrf_token() }}';
// Load conversations.js after data is set
(function() {
var s = document.createElement('script');
s.src = '{{ url_for("static", filename="js/conversations.js") }}?v=6';
s.src = '{{ url_for("static", filename="js/conversations.js") }}?v=7';
document.body.appendChild(s);
})();
{% endblock %}