diff --git a/app/components/channel_list/categories/body/category_body.test.tsx b/app/components/channel_list/categories/body/category_body.test.tsx index 220ac79ae..3a32e3bf2 100644 --- a/app/components/channel_list/categories/body/category_body.test.tsx +++ b/app/components/channel_list/categories/body/category_body.test.tsx @@ -36,6 +36,7 @@ describe('components/channel_list/categories/body', () => { category={category} locale={DEFAULT_LOCALE} currentChannelId={''} + currentUserId={''} />, {database}, ); diff --git a/app/components/channel_list/categories/body/category_body.tsx b/app/components/channel_list/categories/body/category_body.tsx index 017475a9c..2961cf21f 100644 --- a/app/components/channel_list/categories/body/category_body.tsx +++ b/app/components/channel_list/categories/body/category_body.tsx @@ -11,19 +11,27 @@ import type CategoryModel from '@typings/database/models/servers/category'; type Props = { currentChannelId: string; sortedIds: string[]; + hiddenChannelIds: string[]; category: CategoryModel; limit: number; }; const extractKey = (item: string) => item; -const CategoryBody = ({currentChannelId, sortedIds, category, limit}: Props) => { +const CategoryBody = ({currentChannelId, sortedIds, category, hiddenChannelIds, limit}: Props) => { const ids = useMemo(() => { - if (category.type === 'direct_messages' && limit > 0) { - return sortedIds.slice(0, limit - 1); + let filteredIds = sortedIds; + + // Remove all closed gm/dms + if (hiddenChannelIds.length) { + filteredIds = sortedIds.filter((id) => !hiddenChannelIds.includes(id)); } - return sortedIds; - }, [category.type, limit]); + + if (category.type === 'direct_messages' && limit > 0) { + return filteredIds.slice(0, limit - 1); + } + return filteredIds; + }, [category.type, limit, hiddenChannelIds]); const ChannelItem = useCallback(({item}: {item: string}) => { return ( diff --git a/app/components/channel_list/categories/body/index.ts b/app/components/channel_list/categories/body/index.ts index 52cbde4e9..578e21a8b 100644 --- a/app/components/channel_list/categories/body/index.ts +++ b/app/components/channel_list/categories/body/index.ts @@ -8,15 +8,17 @@ import {combineLatest, of as of$} from 'rxjs'; import {switchMap} from 'rxjs/operators'; import {General, Preferences} from '@constants'; -import {queryMyChannelSettingsByIds} from '@queries/servers/channel'; +import {queryChannelsByNames, queryMyChannelSettingsByIds} from '@queries/servers/channel'; import {queryPreferencesByCategoryAndName} from '@queries/servers/preference'; import {WithDatabaseArgs} from '@typings/database/database'; +import {getDirectChannelName} from '@utils/channel'; import CategoryBody from './category_body'; import type CategoryModel from '@typings/database/models/servers/category'; import type ChannelModel from '@typings/database/models/servers/channel'; import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings'; +import type PreferenceModel from '@typings/database/models/servers/preference'; type ChannelData = Pick & { isMuted: boolean; @@ -77,23 +79,51 @@ const getSortedIds = (database: Database, category: CategoryModel, locale: strin } }; -const enhance = withObservables(['category'], ({category, locale, database}: {category: CategoryModel; locale: string} & WithDatabaseArgs) => { +const mapPrefName = (prefs: PreferenceModel[]) => of$(prefs.map((p) => p.name)); + +const mapChannelIds = (channels: ChannelModel[]) => of$(channels.map((c) => c.id)); + +type EnhanceProps = {category: CategoryModel; locale: string; currentUserId: string} & WithDatabaseArgs + +const enhance = withObservables(['category'], ({category, locale, database, currentUserId}: EnhanceProps) => { const observedCategory = category.observe(); const sortedIds = observedCategory.pipe( switchMap((c) => getSortedIds(database, c, locale)), ); - let limit = of$(20); + const dmMap = (p: PreferenceModel) => getDirectChannelName(p.name, currentUserId); + + const hiddenDmIds = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, undefined, 'false'). + observe().pipe( + switchMap((prefs: PreferenceModel[]) => { + const names = prefs.map(dmMap); + const channels = queryChannelsByNames(database, names).observe(); + + return channels.pipe( + switchMap(mapChannelIds), + ); + }), + ); + + const hiddenGmIds = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_GROUP_CHANNEL_SHOW, undefined, 'false'). + observe().pipe(switchMap(mapPrefName)); + + let limit = of$(Preferences.CHANNEL_SIDEBAR_LIMIT_DMS_DEFAULT); if (category.type === 'direct_messages') { - limit = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_SIDEBAR_SETTINGS, 'limit_visible_dms_gms').observe().pipe( + limit = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.CHANNEL_SIDEBAR_LIMIT_DMS).observe().pipe( switchMap((val) => { - return val[0] ? of$(parseInt(val[0].value, 10)) : of$(0); + return val[0] ? of$(parseInt(val[0].value, 10)) : of$(Preferences.CHANNEL_SIDEBAR_LIMIT_DMS_DEFAULT); }), ); } + const hiddenChannelIds = combineLatest([hiddenDmIds, hiddenGmIds]).pipe(switchMap( + ([a, b]) => of$(a.concat(b)), + )); + return { limit, + hiddenChannelIds, sortedIds, category: observedCategory, }; diff --git a/app/components/channel_list/categories/categories.tsx b/app/components/channel_list/categories/categories.tsx index 406b12294..5718fd42b 100644 --- a/app/components/channel_list/categories/categories.tsx +++ b/app/components/channel_list/categories/categories.tsx @@ -14,6 +14,7 @@ import type {CategoryModel} from '@database/models/server'; type Props = { categories: CategoryModel[]; currentChannelId: string; + currentUserId: string; } const styles = StyleSheet.create({ @@ -24,8 +25,9 @@ const styles = StyleSheet.create({ const extractKey = (item: CategoryModel) => item.id; -const Categories = ({categories, currentChannelId}: Props) => { +const Categories = ({categories, currentChannelId, currentUserId}: Props) => { const intl = useIntl(); + const renderCategory = useCallback((data: {item: CategoryModel}) => { return ( <> @@ -33,6 +35,7 @@ const Categories = ({categories, currentChannelId}: Props) => { diff --git a/app/components/channel_list/categories/index.ts b/app/components/channel_list/categories/index.ts index 3029ba123..7ee77ad1c 100644 --- a/app/components/channel_list/categories/index.ts +++ b/app/components/channel_list/categories/index.ts @@ -5,7 +5,7 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; import {queryCategoriesByTeamIds} from '@queries/servers/categories'; -import {observeCurrentChannelId} from '@queries/servers/system'; +import {observeCurrentChannelId, observeCurrentUserId} from '@queries/servers/system'; import Categories from './categories'; @@ -17,11 +17,13 @@ const enhanced = withObservables( ['currentTeamId'], ({currentTeamId, database}: WithDatabaseProps) => { const currentChannelId = observeCurrentChannelId(database); + const currentUserId = observeCurrentUserId(database); const categories = queryCategoriesByTeamIds(database, [currentTeamId]).observeWithColumns(['sort_order']); return { currentChannelId, categories, + currentUserId, }; }); diff --git a/app/constants/preferences.ts b/app/constants/preferences.ts index 0a962329a..ba419d49a 100644 --- a/app/constants/preferences.ts +++ b/app/constants/preferences.ts @@ -35,7 +35,8 @@ const Preferences: Record = { USE_MILITARY_TIME: 'use_military_time', CATEGORY_SIDEBAR_SETTINGS: 'sidebar_settings', CHANNEL_SIDEBAR_ORGANIZATION: 'channel_sidebar_organization', - CHANNEL_SIDEBAR_AUTOCLOSE_DMS: 'close_unused_direct_messages', + CHANNEL_SIDEBAR_LIMIT_DMS: 'limit_visible_dms_gms', + CHANNEL_SIDEBAR_LIMIT_DMS_DEFAULT: 20, AUTOCLOSE_DMS_ENABLED: 'after_seven_days', CATEGORY_ADVANCED_SETTINGS: 'advanced_settings', ADVANCED_FILTER_JOIN_LEAVE: 'join_leave', diff --git a/app/queries/servers/channel.ts b/app/queries/servers/channel.ts index a13defe6d..4bce45aeb 100644 --- a/app/queries/servers/channel.ts +++ b/app/queries/servers/channel.ts @@ -303,3 +303,7 @@ export const queryMyChannelSettingsByIds = (database: Database, ids: string[]) = Q.where('id', Q.oneOf(ids)), ); }; + +export const queryChannelsByNames = (database: Database, names: string[]) => { + return database.get(CHANNEL).query(Q.where('name', Q.oneOf(names))); +}; diff --git a/app/queries/servers/preference.ts b/app/queries/servers/preference.ts index 3f9041836..93aa39f41 100644 --- a/app/queries/servers/preference.ts +++ b/app/queries/servers/preference.ts @@ -12,6 +12,8 @@ import {getCurrentTeamId} from './system'; import type ServerDataOperator from '@database/operator/server_data_operator'; import type PreferenceModel from '@typings/database/models/servers/preference'; +const {SERVER: {PREFERENCE}} = MM_TABLES; + export const prepareMyPreferences = (operator: ServerDataOperator, preferences: PreferenceType[], sync = false) => { try { return operator.handlePreferences({ @@ -32,7 +34,7 @@ export const queryPreferencesByCategoryAndName = (database: Database, category: if (value != null) { clauses.push(Q.where('value', value)); } - return database.get(MM_TABLES.SERVER.PREFERENCE).query(...clauses); + return database.get(PREFERENCE).query(...clauses); }; export const getThemeForCurrentTeam = async (database: Database) => {