[Gekidou] Exclude muted channels from unread badges (#6208)
* Exclude muted channels from unread badges * Gekidou unreads mention fix (#6221) * Removes muted channels without mentions from grouped unreads * show channel if unread and have no mentions when unread up top Co-authored-by: Elias Nahum <nahumhbl@gmail.com> Co-authored-by: Shaz MJ <shaz.amjad@mattermost.com>
This commit is contained in:
parent
588491f582
commit
ecfbb934a8
8 changed files with 71 additions and 27 deletions
|
|
@ -59,7 +59,7 @@ const enhance = withObservables(['channel', 'isUnreads', 'showTeamName'], ({chan
|
|||
return of$(u);
|
||||
}
|
||||
|
||||
return u ? of$(!mc.isUnread) : of$(true);
|
||||
return u ? of$(!mc.isUnread || !mc.mentionsCount) : of$(true);
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {combineLatestWith, map} from 'rxjs/operators';
|
||||
|
||||
import {queryMyChannelsByTeam} from '@queries/servers/channel';
|
||||
import {observeAllMyChannelNotifyProps, queryMyChannelsByTeam} from '@queries/servers/channel';
|
||||
import {observeCurrentTeamId} from '@queries/servers/system';
|
||||
import {observeMentionCount} from '@queries/servers/team';
|
||||
|
||||
|
|
@ -21,9 +20,14 @@ type WithTeamsArgs = WithDatabaseArgs & {
|
|||
|
||||
const enhance = withObservables(['myTeam'], ({myTeam, database}: WithTeamsArgs) => {
|
||||
const myChannels = queryMyChannelsByTeam(database, myTeam.id).observeWithColumns(['mentions_count', 'is_unread']);
|
||||
const notifyProps = observeAllMyChannelNotifyProps(database);
|
||||
const hasUnreads = myChannels.pipe(
|
||||
combineLatestWith(notifyProps),
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
switchMap((val) => of$(val.reduce((acc, v) => acc || v.isUnread, false))),
|
||||
map(([mycs, notify]) => mycs.reduce((acc, v) => {
|
||||
const isMuted = notify?.[v.id]?.mark_unread === 'mention';
|
||||
return acc || (v.isUnread && !isMuted);
|
||||
}, false)),
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -7,18 +7,29 @@ import {combineLatestWith} from 'rxjs/operators';
|
|||
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {observeAllMyChannelNotifyProps} from '@queries/servers/channel';
|
||||
import {queryMyTeams} from '@queries/servers/team';
|
||||
import {getIsCRTEnabled, observeThreadMentionCount, queryThreads} from '@queries/servers/thread';
|
||||
import MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
|
||||
const {SERVER: {CHANNEL, MY_CHANNEL}} = MM_TABLES;
|
||||
|
||||
type ObserverArgs = {
|
||||
export type UnreadObserverArgs = {
|
||||
myChannels: MyChannelModel[];
|
||||
settings?: Record<string, Partial<ChannelNotifyProps>>;
|
||||
threadMentionCount: number;
|
||||
}
|
||||
|
||||
export const subscribeServerUnreadAndMentions = (serverUrl: string, observer: ({myChannels, threadMentionCount}: ObserverArgs) => void) => {
|
||||
type ServerUnreadObserver = {
|
||||
(serverUrl: string, {myChannels, settings, threadMentionCount}: UnreadObserverArgs): void;
|
||||
}
|
||||
|
||||
type UnreadObserver = {
|
||||
({myChannels, settings, threadMentionCount}: UnreadObserverArgs): void;
|
||||
}
|
||||
|
||||
export const subscribeServerUnreadAndMentions = (serverUrl: string, observer: UnreadObserver) => {
|
||||
const server = DatabaseManager.serverDatabases[serverUrl];
|
||||
let subscription: Subscription|undefined;
|
||||
|
||||
|
|
@ -27,8 +38,9 @@ export const subscribeServerUnreadAndMentions = (serverUrl: string, observer: ({
|
|||
query(Q.on(CHANNEL, Q.where('delete_at', Q.eq(0)))).
|
||||
observeWithColumns(['is_unread', 'mentions_count']).
|
||||
pipe(
|
||||
combineLatestWith(observeAllMyChannelNotifyProps(server.database)),
|
||||
combineLatestWith(observeThreadMentionCount(server.database, undefined, false)),
|
||||
map$(([myChannels, threadMentionCount]) => ({myChannels, threadMentionCount})),
|
||||
map$(([[myChannels, settings], threadMentionCount]) => ({myChannels, settings, threadMentionCount})),
|
||||
).
|
||||
subscribe(observer);
|
||||
}
|
||||
|
|
@ -36,7 +48,7 @@ export const subscribeServerUnreadAndMentions = (serverUrl: string, observer: ({
|
|||
return subscription;
|
||||
};
|
||||
|
||||
export const subscribeMentionsByServer = (serverUrl: string, observer: (serverUrl: string, {myChannels, threadMentionCount}: ObserverArgs) => void) => {
|
||||
export const subscribeMentionsByServer = (serverUrl: string, observer: ServerUnreadObserver) => {
|
||||
const server = DatabaseManager.serverDatabases[serverUrl];
|
||||
let subscription: Subscription|undefined;
|
||||
|
||||
|
|
@ -55,7 +67,7 @@ export const subscribeMentionsByServer = (serverUrl: string, observer: (serverUr
|
|||
return subscription;
|
||||
};
|
||||
|
||||
export const subscribeUnreadAndMentionsByServer = (serverUrl: string, observer: (serverUrl: string, {myChannels, threadMentionCount}: ObserverArgs) => void) => {
|
||||
export const subscribeUnreadAndMentionsByServer = (serverUrl: string, observer: ServerUnreadObserver) => {
|
||||
const server = DatabaseManager.serverDatabases[serverUrl];
|
||||
let subscription: Subscription|undefined;
|
||||
|
||||
|
|
@ -64,8 +76,9 @@ export const subscribeUnreadAndMentionsByServer = (serverUrl: string, observer:
|
|||
query(Q.on(CHANNEL, Q.where('delete_at', Q.eq(0)))).
|
||||
observeWithColumns(['mentions_count', 'is_unread']).
|
||||
pipe(
|
||||
combineLatestWith(observeAllMyChannelNotifyProps(server.database)),
|
||||
combineLatestWith(observeThreadMentionCount(server.database, undefined, false)),
|
||||
map$(([myChannels, threadMentionCount]) => ({myChannels, threadMentionCount})),
|
||||
map$(([[myChannels, settings], threadMentionCount]) => ({myChannels, settings, threadMentionCount})),
|
||||
).
|
||||
subscribe(observer.bind(undefined, serverUrl));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import {Database, Model, Q, Query, Relation} from '@nozbe/watermelondb';
|
||||
import {of as of$, Observable} from 'rxjs';
|
||||
import {switchMap, distinctUntilChanged} from 'rxjs/operators';
|
||||
import {map as map$, switchMap, distinctUntilChanged} from 'rxjs/operators';
|
||||
|
||||
import {General, Permissions} from '@constants';
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
|
|
@ -367,6 +367,10 @@ export const observeChannelInfo = (database: Database, channelId: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const queryAllMyChannelSettings = (database: Database) => {
|
||||
return database.get<MyChannelSettingsModel>(MY_CHANNEL_SETTINGS).query();
|
||||
};
|
||||
|
||||
export const queryMyChannelSettingsByIds = (database: Database, ids: string[]) => {
|
||||
return database.get<MyChannelSettingsModel>(MY_CHANNEL_SETTINGS).
|
||||
query(
|
||||
|
|
@ -374,6 +378,15 @@ export const queryMyChannelSettingsByIds = (database: Database, ids: string[]) =
|
|||
);
|
||||
};
|
||||
|
||||
export const observeAllMyChannelNotifyProps = (database: Database) => {
|
||||
return queryAllMyChannelSettings(database).observeWithColumns(['notify_props']).pipe(
|
||||
map$((settings) => settings.reduce<Record<string, Partial<ChannelNotifyProps>>>((obj, setting) => {
|
||||
obj[setting.id] = setting.notifyProps;
|
||||
return obj;
|
||||
}, {})),
|
||||
);
|
||||
};
|
||||
|
||||
export const queryChannelsByNames = (database: Database, names: string[]) => {
|
||||
return database.get<ChannelModel>(CHANNEL).query(Q.where('name', Q.oneOf(names)));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@
|
|||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {of as of$, combineLatest} from 'rxjs';
|
||||
import {concatAll, map, switchMap} from 'rxjs/operators';
|
||||
import {combineLatestWith, concatAll, map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {MyChannelModel} from '@app/database/models/server';
|
||||
import {Preferences} from '@constants';
|
||||
import {getPreferenceAsBool} from '@helpers/api/preference';
|
||||
import {getChannelById, queryMyChannelUnreads} from '@queries/servers/channel';
|
||||
import {getChannelById, observeAllMyChannelNotifyProps, queryMyChannelUnreads} from '@queries/servers/channel';
|
||||
import {queryPreferencesByCategoryAndName} from '@queries/servers/preference';
|
||||
import {observeLastUnreadChannelId} from '@queries/servers/system';
|
||||
|
||||
|
|
@ -31,6 +32,16 @@ const concatenateChannelsArray = ([a, b]: CA) => {
|
|||
return of$(b ? a.filter((c) => c && c.id !== b.id).concat(b) : a);
|
||||
};
|
||||
|
||||
type NotifyProps = {
|
||||
[key: string]: Partial<ChannelNotifyProps>;
|
||||
}
|
||||
|
||||
const filterMutedFromMyChannels = ([myChannels, notifyProps]: [MyChannelModel[], NotifyProps]) => {
|
||||
return myChannels.filter(
|
||||
(myChannel) => notifyProps[myChannel.id]?.mark_unread !== 'mention' || myChannel.mentionsCount > 0, // Muted with Mentions should still go through
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withObservables(['currentTeamId'], ({currentTeamId, database}: WithDatabaseProps) => {
|
||||
const unreadsOnTop = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.CHANNEL_SIDEBAR_GROUP_UNREADS).
|
||||
observeWithColumns(['value']).
|
||||
|
|
@ -45,8 +56,11 @@ const enhanced = withObservables(['currentTeamId'], ({currentTeamId, database}:
|
|||
const lastUnread = observeLastUnreadChannelId(database).pipe(
|
||||
switchMap(getC),
|
||||
);
|
||||
const notifyProps = observeAllMyChannelNotifyProps(database);
|
||||
|
||||
const unreads = queryMyChannelUnreads(database, currentTeamId).observe().pipe(
|
||||
combineLatestWith(notifyProps),
|
||||
map(filterMutedFromMyChannels),
|
||||
map(getChannelsFromRelation),
|
||||
concatAll(),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,14 +9,13 @@ import ServerIcon from '@components/server_icon';
|
|||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {subscribeAllServers} from '@database/subscription/servers';
|
||||
import {subscribeUnreadAndMentionsByServer} from '@database/subscription/unreads';
|
||||
import {subscribeUnreadAndMentionsByServer, UnreadObserverArgs} from '@database/subscription/unreads';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import {bottomSheet} from '@screens/navigation';
|
||||
|
||||
import ServerList from './servers_list';
|
||||
|
||||
import type ServersModel from '@typings/database/models/app/servers';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type {UnreadMessages, UnreadSubscription} from '@typings/database/subscriptions';
|
||||
|
||||
const subscriptions: Map<string, UnreadSubscription> = new Map();
|
||||
|
|
@ -70,14 +69,15 @@ const Servers = React.forwardRef<ServersRef>((props, ref) => {
|
|||
setTotal({mentions, unread});
|
||||
};
|
||||
|
||||
const unreadsSubscription = (serverUrl: string, {myChannels, threadMentionCount}: {myChannels: MyChannelModel[]; threadMentionCount: number}) => {
|
||||
const unreadsSubscription = (serverUrl: string, {myChannels, settings, threadMentionCount}: UnreadObserverArgs) => {
|
||||
const unreads = subscriptions.get(serverUrl);
|
||||
if (unreads) {
|
||||
let mentions = 0;
|
||||
let unread = false;
|
||||
for (const myChannel of myChannels) {
|
||||
const isMuted = settings?.[myChannel.id]?.mark_unread === 'mention';
|
||||
mentions += myChannel.mentionsCount;
|
||||
unread = unread || myChannel.isUnread;
|
||||
unread = unread || (myChannel.isUnread && !isMuted);
|
||||
}
|
||||
|
||||
unreads.mentions = mentions + threadMentionCount;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import TutorialSwipeLeft from '@components/tutorial_highlight/swipe_left';
|
|||
import {Events} from '@constants';
|
||||
import {useTheme} from '@context/theme';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {subscribeServerUnreadAndMentions} from '@database/subscription/unreads';
|
||||
import {subscribeServerUnreadAndMentions, UnreadObserverArgs} from '@database/subscription/unreads';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import {dismissBottomSheet} from '@screens/navigation';
|
||||
import {alertServerError, alertServerLogout, alertServerRemove, editServer, loginToServer} from '@utils/server';
|
||||
|
|
@ -32,7 +32,6 @@ import Options from './options';
|
|||
import WebSocket from './websocket';
|
||||
|
||||
import type ServersModel from '@typings/database/models/app/servers';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type {Subscription} from 'rxjs';
|
||||
|
||||
type Props = {
|
||||
|
|
@ -138,12 +137,13 @@ const ServerItem = ({highlight, isActive, server, tutorialWatched}: Props) => {
|
|||
displayName = intl.formatMessage({id: 'servers.default', defaultMessage: 'Default Server'});
|
||||
}
|
||||
|
||||
const unreadsSubscription = ({myChannels, threadMentionCount}: {myChannels: MyChannelModel[]; threadMentionCount: number}) => {
|
||||
const unreadsSubscription = ({myChannels, settings, threadMentionCount}: UnreadObserverArgs) => {
|
||||
let mentions = 0;
|
||||
let isUnread = false;
|
||||
for (const myChannel of myChannels) {
|
||||
const isMuted = settings?.[myChannel.id]?.mark_unread === 'mention';
|
||||
mentions += myChannel.mentionsCount;
|
||||
isUnread = isUnread || myChannel.isUnread;
|
||||
isUnread = isUnread || (myChannel.isUnread && !isMuted);
|
||||
}
|
||||
mentions += threadMentionCount;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ import Badge from '@components/badge';
|
|||
import CompassIcon from '@components/compass_icon';
|
||||
import {BOTTOM_TAB_ICON_SIZE} from '@constants/view';
|
||||
import {subscribeAllServers} from '@database/subscription/servers';
|
||||
import {subscribeUnreadAndMentionsByServer} from '@database/subscription/unreads';
|
||||
import {subscribeUnreadAndMentionsByServer, UnreadObserverArgs} from '@database/subscription/unreads';
|
||||
import {changeOpacity} from '@utils/theme';
|
||||
|
||||
import type ServersModel from '@typings/database/models/app/servers';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type {UnreadMessages, UnreadSubscription} from '@typings/database/subscriptions';
|
||||
|
||||
type Props = {
|
||||
|
|
@ -51,14 +50,15 @@ const Home = ({isFocused, theme}: Props) => {
|
|||
setTotal({mentions, unread});
|
||||
};
|
||||
|
||||
const unreadsSubscription = (serverUrl: string, {myChannels, threadMentionCount}: {myChannels: MyChannelModel[]; threadMentionCount: number}) => {
|
||||
const unreadsSubscription = (serverUrl: string, {myChannels, settings, threadMentionCount}: UnreadObserverArgs) => {
|
||||
const unreads = subscriptions.get(serverUrl);
|
||||
if (unreads) {
|
||||
let mentions = 0;
|
||||
let unread = false;
|
||||
for (const myChannel of myChannels) {
|
||||
const isMuted = settings?.[myChannel.id]?.mark_unread === 'mention';
|
||||
mentions += myChannel.mentionsCount;
|
||||
unread = unread || myChannel.isUnread;
|
||||
unread = unread || (myChannel.isUnread && !isMuted);
|
||||
}
|
||||
|
||||
unreads.mentions = mentions + threadMentionCount;
|
||||
|
|
|
|||
Loading…
Reference in a new issue