mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-11-24 18:25:41 +03:00
Improve grouping for server-side grouping
Migrate from v2_alpha to v2
This commit is contained in:
parent
4cc6a6a12c
commit
c8abb95e8e
3 changed files with 150 additions and 48 deletions
|
@ -3,6 +3,7 @@ import { useLingui } from '@lingui/react';
|
||||||
import { Fragment } from 'preact';
|
import { Fragment } from 'preact';
|
||||||
import { memo } from 'preact/compat';
|
import { memo } from 'preact/compat';
|
||||||
|
|
||||||
|
import { api } from '../utils/api';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
import states, { statusKey } from '../utils/states';
|
import states, { statusKey } from '../utils/states';
|
||||||
import { getCurrentAccountID } from '../utils/store-utils';
|
import { getCurrentAccountID } from '../utils/store-utils';
|
||||||
|
@ -302,6 +303,7 @@ function Notification({
|
||||||
disableContextMenu,
|
disableContextMenu,
|
||||||
}) {
|
}) {
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
|
const { masto } = api();
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
status,
|
status,
|
||||||
|
@ -313,9 +315,11 @@ function Notification({
|
||||||
_ids,
|
_ids,
|
||||||
_accounts,
|
_accounts,
|
||||||
_statuses,
|
_statuses,
|
||||||
|
_groupKeys,
|
||||||
// Server-side grouped notification
|
// Server-side grouped notification
|
||||||
sampleAccounts,
|
sampleAccounts,
|
||||||
notificationsCount,
|
notificationsCount,
|
||||||
|
groupKey,
|
||||||
} = notification;
|
} = notification;
|
||||||
let { type } = notification;
|
let { type } = notification;
|
||||||
|
|
||||||
|
@ -443,10 +447,15 @@ function Notification({
|
||||||
|
|
||||||
console.debug('RENDER Notification', notification.id);
|
console.debug('RENDER Notification', notification.id);
|
||||||
|
|
||||||
|
const sameCount =
|
||||||
|
notificationsCount > 0 && notificationsCount <= sampleAccounts?.length;
|
||||||
|
const expandAccounts = sameCount ? 'local' : 'remote';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={`notification notification-${type}`}
|
class={`notification notification-${type}`}
|
||||||
data-notification-id={_ids || id}
|
data-notification-id={_ids || id}
|
||||||
|
data-group-key={_groupKeys?.join(' ') || groupKey}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -550,6 +559,57 @@ function Notification({
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
|
{type === 'favourite+reblog' && expandAccounts === 'remote' ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="small plain"
|
||||||
|
data-group-keys={_groupKeys.join(' ')}
|
||||||
|
onClick={() => {
|
||||||
|
states.showGenericAccounts = {
|
||||||
|
heading: genericAccountsHeading,
|
||||||
|
fetchAccounts: async () => {
|
||||||
|
const keyAccounts = await Promise.allSettled(
|
||||||
|
_groupKeys.map(async (gKey) => {
|
||||||
|
const iterator = masto.v2.notifications
|
||||||
|
.$select(gKey)
|
||||||
|
.accounts.list();
|
||||||
|
return [gKey, (await iterator.next()).value];
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const accounts = [];
|
||||||
|
for (const keyAccount of keyAccounts) {
|
||||||
|
const [key, _accounts] = keyAccount.value;
|
||||||
|
const type = /^favourite/.test(key)
|
||||||
|
? 'favourite'
|
||||||
|
: /^reblog/.test(key)
|
||||||
|
? 'reblog'
|
||||||
|
: null;
|
||||||
|
if (!type) continue;
|
||||||
|
for (const account of _accounts) {
|
||||||
|
const theAccount = accounts.find(
|
||||||
|
(a) => a.id === account.id,
|
||||||
|
);
|
||||||
|
if (theAccount) {
|
||||||
|
theAccount._types.push(type);
|
||||||
|
} else {
|
||||||
|
account._types = [type];
|
||||||
|
accounts.push(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
done: true,
|
||||||
|
value: accounts,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
showReactions: true,
|
||||||
|
postID: statusKey(actualStatusID, instance),
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon icon="chevron-down" />
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="small plain"
|
class="small plain"
|
||||||
|
@ -559,6 +619,7 @@ function Notification({
|
||||||
`+${_accounts.length - AVATARS_LIMIT}`}
|
`+${_accounts.length - AVATARS_LIMIT}`}
|
||||||
<Icon icon="chevron-down" />
|
<Icon icon="chevron-down" />
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{!_accounts?.length && sampleAccounts?.length > 1 && (
|
{!_accounts?.length && sampleAccounts?.length > 1 && (
|
||||||
|
|
|
@ -69,7 +69,7 @@ export function mastoFetchNotifications(opts = {}) {
|
||||||
memSupportsGroupedNotifications()
|
memSupportsGroupedNotifications()
|
||||||
) {
|
) {
|
||||||
// https://github.com/mastodon/mastodon/pull/29889
|
// https://github.com/mastodon/mastodon/pull/29889
|
||||||
return masto.v2_alpha.notifications.list({
|
return masto.v2.notifications.list({
|
||||||
limit: NOTIFICATIONS_GROUPED_LIMIT,
|
limit: NOTIFICATIONS_GROUPED_LIMIT,
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,66 +68,105 @@ export function groupNotifications2(groupNotifications) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// DISABLED FOR NOW.
|
|
||||||
// Merge favourited and reblogged of same status into a single notification
|
// Merge favourited and reblogged of same status into a single notification
|
||||||
// - new type: "favourite+reblog"
|
// - new type: "favourite+reblog"
|
||||||
// - sum numbers for `notificationsCount` and `sampleAccounts`
|
// - sum numbers for `notificationsCount` and `sampleAccounts`
|
||||||
// const mappedNotifications = {};
|
const notificationsMap = {};
|
||||||
// const newNewGroupNotifications = [];
|
const newGroupNotifications1 = [];
|
||||||
// for (let i = 0; i < newGroupNotifications.length; i++) {
|
for (let i = 0; i < newGroupNotifications.length; i++) {
|
||||||
// const gn = newGroupNotifications[i];
|
const gn = newGroupNotifications[i];
|
||||||
// const { type, status, createdAt, notificationsCount, sampleAccounts } = gn;
|
const {
|
||||||
// const date = createdAt ? new Date(createdAt).toLocaleDateString() : '';
|
type,
|
||||||
// let virtualType = type;
|
status,
|
||||||
// if (type === 'favourite' || type === 'reblog') {
|
createdAt,
|
||||||
// virtualType = 'favourite+reblog';
|
notificationsCount,
|
||||||
// }
|
sampleAccounts,
|
||||||
// const key = `${status?.id}-${virtualType}-${date}`;
|
groupKey,
|
||||||
// const mappedNotification = mappedNotifications[key];
|
} = gn;
|
||||||
// if (mappedNotification) {
|
const date = createdAt ? new Date(createdAt).toLocaleDateString() : '';
|
||||||
// const accountIDs = mappedNotification.sampleAccounts.map((a) => a.id);
|
let virtualType = type;
|
||||||
// sampleAccounts.forEach((a) => {
|
const sameCount =
|
||||||
// if (!accountIDs.includes(a.id)) {
|
notificationsCount > 0 && notificationsCount === sampleAccounts?.length;
|
||||||
// mappedNotification.sampleAccounts.push(a);
|
// if (sameCount && (type === 'favourite' || type === 'reblog')) {
|
||||||
// }
|
if (type === 'favourite' || type === 'reblog') {
|
||||||
// });
|
virtualType = 'favourite+reblog';
|
||||||
// mappedNotification.notificationsCount = Math.max(
|
}
|
||||||
// mappedNotification.notificationsCount,
|
// const key = `${status?.id}-${virtualType}-${date}-${sameCount ? 1 : 0}`;
|
||||||
// notificationsCount,
|
const key = `${status?.id}-${virtualType}-${date}`;
|
||||||
// mappedNotification.sampleAccounts.length,
|
const mappedNotification = notificationsMap[key];
|
||||||
// );
|
if (mappedNotification) {
|
||||||
// } else {
|
// Merge sampleAccounts + merge _types
|
||||||
// mappedNotifications[key] = {
|
sampleAccounts.forEach((a) => {
|
||||||
// ...gn,
|
const mappedAccount = mappedNotification.sampleAccounts.find(
|
||||||
// type: virtualType,
|
(ma) => ma.id === a.id,
|
||||||
// };
|
);
|
||||||
// newNewGroupNotifications.push(mappedNotifications[key]);
|
if (!mappedAccount) {
|
||||||
// }
|
mappedNotification.sampleAccounts.push({
|
||||||
// }
|
...a,
|
||||||
|
_types: [type],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
mappedAccount._types.push(type);
|
||||||
|
mappedAccount._types.sort().reverse();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// mappedNotification.notificationsCount =
|
||||||
|
// mappedNotification.sampleAccounts.length;
|
||||||
|
mappedNotification.notificationsCount = Math.min(
|
||||||
|
mappedNotification.notificationsCount,
|
||||||
|
notificationsCount,
|
||||||
|
);
|
||||||
|
mappedNotification._notificationsCount.push(notificationsCount);
|
||||||
|
mappedNotification._accounts = mappedNotification.sampleAccounts;
|
||||||
|
mappedNotification._groupKeys.push(groupKey);
|
||||||
|
} else {
|
||||||
|
const accounts = sampleAccounts.map((a) => ({
|
||||||
|
...a,
|
||||||
|
_types: [type],
|
||||||
|
}));
|
||||||
|
notificationsMap[key] = {
|
||||||
|
...gn,
|
||||||
|
sampleAccounts: accounts,
|
||||||
|
type: virtualType,
|
||||||
|
_accounts: accounts,
|
||||||
|
_groupKeys: groupKey ? [groupKey] : [],
|
||||||
|
_notificationsCount: [notificationsCount],
|
||||||
|
};
|
||||||
|
newGroupNotifications1.push(notificationsMap[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 2nd pass.
|
// 2nd pass.
|
||||||
// - Group 1 account favourte/reblog multiple posts
|
// - Group 1 account favourte/reblog multiple posts
|
||||||
// - _statuses: [status, status, ...]
|
// - _statuses: [status, status, ...]
|
||||||
const notificationsMap2 = {};
|
const notificationsMap2 = {};
|
||||||
const newGroupNotifications2 = [];
|
const newGroupNotifications2 = [];
|
||||||
for (let i = 0; i < newGroupNotifications.length; i++) {
|
for (let i = 0; i < newGroupNotifications1.length; i++) {
|
||||||
const gn = newGroupNotifications[i];
|
const gn = newGroupNotifications1[i];
|
||||||
const { type, account, _accounts, sampleAccounts, createdAt } = gn;
|
const { type, account, _accounts, sampleAccounts, createdAt, groupKey } =
|
||||||
|
gn;
|
||||||
const date = createdAt ? new Date(createdAt).toLocaleDateString() : '';
|
const date = createdAt ? new Date(createdAt).toLocaleDateString() : '';
|
||||||
const hasOneAccount =
|
const hasOneAccount =
|
||||||
sampleAccounts?.length === 1 || _accounts?.length === 1;
|
sampleAccounts?.length === 1 || _accounts?.length === 1;
|
||||||
if ((type === 'favourite' || type === 'reblog') && hasOneAccount) {
|
if (
|
||||||
|
(type === 'favourite' ||
|
||||||
|
type === 'reblog' ||
|
||||||
|
type === 'favourite+reblog') &&
|
||||||
|
hasOneAccount
|
||||||
|
) {
|
||||||
const key = `${account?.id}-${type}-${date}`;
|
const key = `${account?.id}-${type}-${date}`;
|
||||||
const mappedNotification = notificationsMap2[key];
|
const mappedNotification = notificationsMap2[key];
|
||||||
if (mappedNotification) {
|
if (mappedNotification) {
|
||||||
mappedNotification._statuses.push(gn.status);
|
mappedNotification._statuses.push(gn.status);
|
||||||
mappedNotification._ids += `-${gn.id}`;
|
mappedNotification._ids += `-${gn.id}`;
|
||||||
|
mappedNotification._groupKeys.push(groupKey);
|
||||||
} else {
|
} else {
|
||||||
let n = (notificationsMap2[key] = {
|
let n = (notificationsMap2[key] = {
|
||||||
...gn,
|
...gn,
|
||||||
type,
|
type,
|
||||||
_ids: gn.id,
|
_ids: gn.id,
|
||||||
_statuses: [gn.status],
|
_statuses: [gn.status],
|
||||||
|
_groupKeys: groupKey ? [groupKey] : [],
|
||||||
});
|
});
|
||||||
newGroupNotifications2.push(n);
|
newGroupNotifications2.push(n);
|
||||||
}
|
}
|
||||||
|
@ -136,6 +175,8 @@ export function groupNotifications2(groupNotifications) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('newGroupNotifications2', newGroupNotifications2);
|
||||||
|
|
||||||
return newGroupNotifications2;
|
return newGroupNotifications2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue