SHA256
Fix unread channel counts and badges
This commit is contained in:
+1
-1
@@ -161,7 +161,7 @@ final class ChannelsReadSupport {
|
|||||||
AND setting_key = ?
|
AND setting_key = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""";
|
""";
|
||||||
long lastSeen = messagesCount;
|
long lastSeen = 0;
|
||||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||||
ps.setString(1, viewerLogin);
|
ps.setString(1, viewerLogin);
|
||||||
ps.setInt(2, 1);
|
ps.setInt(2, 1);
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
7. `GetGroupDialog` — отдает сообщения конкретного группового чата типа `200`.
|
7. `GetGroupDialog` — отдает сообщения конкретного группового чата типа `200`.
|
||||||
|
|
||||||
> На первом этапе мы **не используем курсоры** (`nextCursor`) и загружаем полные списки.
|
> На первом этапе мы **не используем курсоры** (`nextCursor`) и загружаем полные списки.
|
||||||
|
>
|
||||||
|
> `unreadCount` для канала считается по `user_settings`:
|
||||||
|
> если для пары `ownerBlockchainName/channelName` ещё нет записи, канал считается полностью непросмотренным.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
- `value_num = number of messages already seen in channel`;
|
- `value_num = number of messages already seen in channel`;
|
||||||
- `value_text = ''`.
|
- `value_text = ''`.
|
||||||
|
|
||||||
Если настройки нет, канал считается просмотренным до конца, то есть unread = `0`.
|
Если настройки нет, канал считается полностью непросмотренным, то есть unread = `messagesCount`.
|
||||||
|
После первого открытия канала UI отправляет актуальный курсор и тем самым переводит unread к `0`.
|
||||||
|
|
||||||
## 2. Структура записи
|
## 2. Структура записи
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ function buildThreadRoute(messageRef, selector) {
|
|||||||
function buildChannelSettingsKey(ownerBlockchainName, channelName) {
|
function buildChannelSettingsKey(ownerBlockchainName, channelName) {
|
||||||
const ownerBch = String(ownerBlockchainName || '').trim();
|
const ownerBch = String(ownerBlockchainName || '').trim();
|
||||||
const name = String(channelName || '').trim();
|
const name = String(channelName || '').trim();
|
||||||
|
if (!ownerBch || !name) return '';
|
||||||
return `${ownerBch}/${name}`;
|
return `${ownerBch}/${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1370,7 +1371,7 @@ async function loadFromApi(route, channelId) {
|
|||||||
throw new Error('Канал не найден.');
|
throw new Error('Канал не найден.');
|
||||||
}
|
}
|
||||||
unreadCount = Number(channel?.unreadCount || 0);
|
unreadCount = Number(channel?.unreadCount || 0);
|
||||||
messagesCount = Number(channel?.messagesCount || mergedMessages.length || 0);
|
messagesCount = Number(channel?.messagesCount || 0);
|
||||||
selector = {
|
selector = {
|
||||||
ownerBlockchainName: String(channel.channel.ownerBlockchainName),
|
ownerBlockchainName: String(channel.channel.ownerBlockchainName),
|
||||||
channelRootBlockNumber: Number(channel.channel.channelRoot.blockNumber),
|
channelRootBlockNumber: Number(channel.channel.channelRoot.blockNumber),
|
||||||
@@ -1447,6 +1448,7 @@ async function loadFromApi(route, channelId) {
|
|||||||
return {
|
return {
|
||||||
channel: {
|
channel: {
|
||||||
name: payload.channel?.channelName || 'неизвестный канал',
|
name: payload.channel?.channelName || 'неизвестный канал',
|
||||||
|
ownerBlockchainName: String(payload.channel?.ownerBlockchainName || '').trim(),
|
||||||
displayTitle: String(payload.channel?.displayName || payload.channel?.channelName || 'неизвестный канал').trim(),
|
displayTitle: String(payload.channel?.displayName || payload.channel?.channelName || 'неизвестный канал').trim(),
|
||||||
displayName: `${ownerLogin || 'неизвестно'}/${payload.channel?.channelName || 'неизвестный канал'}`,
|
displayName: `${ownerLogin || 'неизвестно'}/${payload.channel?.channelName || 'неизвестный канал'}`,
|
||||||
description: String(payload.channel?.channelDescription || '').trim(),
|
description: String(payload.channel?.channelDescription || '').trim(),
|
||||||
@@ -2318,7 +2320,10 @@ export function render({ navigate, route, chrome }) {
|
|||||||
const apiData = await loadFromApi(route, channelId);
|
const apiData = await loadFromApi(route, channelId);
|
||||||
activeSelector = apiData?.selector || null;
|
activeSelector = apiData?.selector || null;
|
||||||
const lastSeenCount = Number(apiData?.messagesCount || (Array.isArray(apiData?.posts) ? apiData.posts.length : 0) || 0);
|
const lastSeenCount = Number(apiData?.messagesCount || (Array.isArray(apiData?.posts) ? apiData.posts.length : 0) || 0);
|
||||||
const settingKey = buildChannelSettingsKey(apiData?.channel?.ownerBlockchainName, apiData?.channel?.name);
|
const settingKey = buildChannelSettingsKey(
|
||||||
|
apiData?.channel?.ownerBlockchainName || apiData?.selector?.ownerBlockchainName,
|
||||||
|
apiData?.channel?.name || apiData?.channel?.channelName,
|
||||||
|
);
|
||||||
if (settingKey && state.session.login && state.session.storagePwdInMemory) {
|
if (settingKey && state.session.login && state.session.storagePwdInMemory) {
|
||||||
void authService.upsertUserSetting({
|
void authService.upsertUserSetting({
|
||||||
login: state.session.login,
|
login: state.session.login,
|
||||||
|
|||||||
@@ -1230,8 +1230,6 @@ function renderListContent({ screen, container, listState, navigate, refreshFeed
|
|||||||
const count = document.createElement('span');
|
const count = document.createElement('span');
|
||||||
count.className = 'unread channel-row-count';
|
count.className = 'unread channel-row-count';
|
||||||
const unreadCount = Number(channel.unreadCount || 0);
|
const unreadCount = Number(channel.unreadCount || 0);
|
||||||
count.textContent = unreadCount > 0 ? String(unreadCount) : '';
|
|
||||||
count.classList.toggle('is-empty', unreadCount <= 0);
|
|
||||||
|
|
||||||
if (!isGuest) {
|
if (!isGuest) {
|
||||||
const menuButton = document.createElement('button');
|
const menuButton = document.createElement('button');
|
||||||
@@ -1261,7 +1259,11 @@ function renderListContent({ screen, container, listState, navigate, refreshFeed
|
|||||||
});
|
});
|
||||||
controls.append(menuButton);
|
controls.append(menuButton);
|
||||||
}
|
}
|
||||||
controls.append(time, count);
|
controls.append(time);
|
||||||
|
if (unreadCount > 0) {
|
||||||
|
count.textContent = unreadCount > 99 ? '99+' : String(unreadCount);
|
||||||
|
controls.append(count);
|
||||||
|
}
|
||||||
|
|
||||||
row.append(avatar, main, controls);
|
row.append(avatar, main, controls);
|
||||||
row.addEventListener('click', () => {
|
row.addEventListener('click', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user