mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Pin conversations WIP. Pinning functioning and persisting on conversation list.
This commit is contained in:
parent
4e8dcefa9a
commit
6dd7f34e4d
|
@ -22,6 +22,8 @@ import { OutgoingMessageStatus } from './conversation/message/OutgoingMessageSta
|
|||
import { DefaultTheme, withTheme } from 'styled-components';
|
||||
import { PubKey } from '../session/types';
|
||||
import { ConversationType, openConversationExternal } from '../state/ducks/conversations';
|
||||
import { SessionIcon, SessionIconSize, SessionIconType } from './session/icon';
|
||||
import { SessionButtonColor } from './session/SessionButton';
|
||||
|
||||
export interface ConversationListItemProps extends ConversationType {
|
||||
index?: number; // used to force a refresh when one conversation is removed on top of the list
|
||||
|
@ -63,7 +65,7 @@ class ConversationListItem extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
public renderHeader() {
|
||||
const { unreadCount, mentionedUs, activeAt } = this.props;
|
||||
const { unreadCount, mentionedUs, activeAt, isPinned } = this.props;
|
||||
|
||||
let atSymbol = null;
|
||||
let unreadCountDiv = null;
|
||||
|
@ -81,7 +83,15 @@ class ConversationListItem extends React.PureComponent<Props> {
|
|||
)}
|
||||
>
|
||||
{this.renderUser()}
|
||||
|
||||
</div>
|
||||
{isPinned ?
|
||||
<SessionIcon
|
||||
iconType={SessionIconType.Pin}
|
||||
iconColor={this.props.theme.colors.textColorSubtle}
|
||||
iconSize={SessionIconSize.Tiny} />
|
||||
: null
|
||||
}
|
||||
{unreadCountDiv}
|
||||
{atSymbol}
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { AutoSizer, List } from 'react-virtualized';
|
||||
|
||||
import { MainViewController } from '../MainViewController';
|
||||
|
@ -81,12 +81,17 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element => {
|
||||
const { conversations, openConversationExternal } = this.props;
|
||||
const { openConversationExternal } = this.props;
|
||||
let { conversations } = this.props;
|
||||
|
||||
if (!conversations) {
|
||||
throw new Error('renderRow: Tried to render without conversations');
|
||||
}
|
||||
|
||||
conversations = _.sortBy([...conversations], (convo) => {
|
||||
return convo.isPinned ? -1 : 1
|
||||
});
|
||||
|
||||
const conversation = conversations[index];
|
||||
|
||||
return (
|
||||
|
@ -100,7 +105,8 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
public renderList(): JSX.Element | Array<JSX.Element | null> {
|
||||
const { conversations, openConversationExternal, searchResults } = this.props;
|
||||
let { conversations } = this.props;
|
||||
const { openConversationExternal, searchResults } = this.props;
|
||||
const contacts = searchResults?.contacts || [];
|
||||
|
||||
if (searchResults) {
|
||||
|
|
|
@ -25,6 +25,7 @@ export enum SessionIconType {
|
|||
Moon = 'moon',
|
||||
Pause = 'pause',
|
||||
Pencil = 'pencil',
|
||||
Pin = 'pin',
|
||||
Play = 'play',
|
||||
Plus = 'plus',
|
||||
Reply = 'reply',
|
||||
|
@ -220,6 +221,12 @@ export const icons = {
|
|||
viewBox: '1 1 21 21',
|
||||
ratio: 1,
|
||||
},
|
||||
[SessionIconType.Pin]: {
|
||||
path:
|
||||
'M83.88.451L122.427 39c.603.601.603 1.585 0 2.188l-13.128 13.125c-.602.604-1.586.604-2.187 0l-3.732-3.73-17.303 17.3c3.882 14.621.095 30.857-11.37 42.32-.266.268-.535.529-.808.787-1.004.955-.843.949-1.813-.021L47.597 86.48 0 122.867l36.399-47.584L11.874 50.76c-.978-.98-.896-.826.066-1.837.24-.251.485-.503.734-.753C24.137 36.707 40.376 32.917 54.996 36.8l17.301-17.3-3.733-3.732c-.601-.601-.601-1.585 0-2.188L81.691.451c.604-.601 1.588-.601 2.189 0z',
|
||||
viewBox: '0 0 122.879 122.867',
|
||||
ratio: 1,
|
||||
},
|
||||
[SessionIconType.Play]: {
|
||||
path:
|
||||
'M29.462,15.707c0,1.061-0.562,2.043-1.474,2.583L6.479,30.999c-0.47,0.275-0.998,0.417-1.526,0.417 c-0.513,0-1.026-0.131-1.487-0.396c-0.936-0.534-1.513-1.527-1.513-2.604V2.998c0-1.077,0.578-2.07,1.513-2.605 C4.402-0.139,5.553-0.13,6.479,0.415l21.509,12.709C28.903,13.664,29.462,14.646,29.462,15.707z',
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
getInviteContactMenuItem,
|
||||
getLeaveGroupMenuItem,
|
||||
getMarkAllReadMenuItem,
|
||||
MenuItemPinConversation
|
||||
} from './Menu';
|
||||
|
||||
export type PropsContextConversationItem = {
|
||||
|
@ -46,6 +47,7 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI
|
|||
return (
|
||||
<>
|
||||
<Menu id={triggerId} animation={animation.fade}>
|
||||
<MenuItemPinConversation conversationId={conversationId} />
|
||||
{getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)}
|
||||
{getCopyMenuItem(isPublic, isGroup, conversationId)}
|
||||
{getMarkAllReadMenuItem(conversationId)}
|
||||
|
|
|
@ -4,8 +4,8 @@ import { NotificationForConvoOption, TimerOption } from '../../conversation/Conv
|
|||
import { Item, Submenu } from 'react-contexify';
|
||||
import { ConversationNotificationSettingType } from '../../../models/conversation';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { actions as conversationActions } from '../../../state/ducks/conversations';
|
||||
import {
|
||||
adminLeaveClosedGroup,
|
||||
changeNickNameModal,
|
||||
updateConfirmModal,
|
||||
} from '../../../state/ducks/modalDialog';
|
||||
|
@ -25,6 +25,8 @@ import {
|
|||
showUpdateGroupNameByConvoId,
|
||||
unblockConvoById,
|
||||
} from '../../../interactions/conversationInteractions';
|
||||
import { purgeStoredState } from 'redux-persist';
|
||||
import { persistConfig, _purgedStoredState } from '../../../state/createStore';
|
||||
|
||||
function showTimerOptions(
|
||||
isPublic: boolean,
|
||||
|
@ -125,6 +127,30 @@ export function getInviteContactMenuItem(
|
|||
return null;
|
||||
}
|
||||
|
||||
export interface PinConversationMenuItemProps {
|
||||
conversationId: string;
|
||||
}
|
||||
|
||||
export const MenuItemPinConversation = (props: PinConversationMenuItemProps): JSX.Element | null => {
|
||||
const { conversationId } = props;
|
||||
const conversation = getConversationController().get(conversationId).getProps();
|
||||
const { isPinned } = conversation;
|
||||
|
||||
const togglePinConversation = () => {
|
||||
window.inboxStore?.dispatch(conversationActions.conversationChanged(conversationId,
|
||||
{
|
||||
...conversation,
|
||||
isPinned: !isPinned
|
||||
}))
|
||||
|
||||
if (isPinned) {
|
||||
// purgeStoredState(persistConfig);
|
||||
}
|
||||
}
|
||||
|
||||
return <Item onClick={togglePinConversation}>{(isPinned ? 'Unpin' : 'Pin') + ' Conversation'}</Item>
|
||||
}
|
||||
|
||||
export function getDeleteContactMenuItem(
|
||||
isMe: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
|
@ -297,7 +323,7 @@ export function getDisappearingMenuItem(
|
|||
// Remove the && false to make context menu work with RTL support
|
||||
<Submenu
|
||||
label={window.i18n('disappearingMessages') as any}
|
||||
// rtl={isRtlMode && false}
|
||||
// rtl={isRtlMode && false}
|
||||
>
|
||||
{(timerOptions || []).map(item => (
|
||||
<Item
|
||||
|
@ -330,7 +356,7 @@ export function getNotificationForConvoMenuItem(
|
|||
// Remove the && false to make context menu work with RTL support
|
||||
<Submenu
|
||||
label={window.i18n('notificationForConvo') as any}
|
||||
// rtl={isRtlMode && false}
|
||||
// rtl={isRtlMode && false}
|
||||
>
|
||||
{(notificationForConvoOptions || []).map(item => {
|
||||
const disabled = item.value === currentNotificationSetting;
|
||||
|
|
|
@ -408,9 +408,14 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|||
left: !!this.get('left'),
|
||||
groupAdmins,
|
||||
members,
|
||||
isPinned: this.getIsPinned() || false
|
||||
};
|
||||
}
|
||||
|
||||
private getIsPinned() {
|
||||
return window.inboxStore?.getState().conversations.conversationLookup[this.id].isPinned;
|
||||
}
|
||||
|
||||
public async updateGroupAdmins(groupAdmins: Array<string>) {
|
||||
const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins()));
|
||||
const newAdmins = _.uniq(_.sortBy(groupAdmins));
|
||||
|
@ -501,9 +506,9 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|||
fileName: fileName || null,
|
||||
thumbnail: thumbnail
|
||||
? {
|
||||
...(await loadAttachmentData(thumbnail)),
|
||||
objectUrl: getAbsoluteAttachmentPath(thumbnail.path),
|
||||
}
|
||||
...(await loadAttachmentData(thumbnail)),
|
||||
objectUrl: getAbsoluteAttachmentPath(thumbnail.path),
|
||||
}
|
||||
: null,
|
||||
};
|
||||
})
|
||||
|
@ -526,9 +531,9 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|||
fileName: null,
|
||||
thumbnail: image
|
||||
? {
|
||||
...(await loadAttachmentData(image)),
|
||||
objectUrl: getAbsoluteAttachmentPath(image.path),
|
||||
}
|
||||
...(await loadAttachmentData(image)),
|
||||
objectUrl: getAbsoluteAttachmentPath(image.path),
|
||||
}
|
||||
: null,
|
||||
};
|
||||
})
|
||||
|
|
|
@ -6,6 +6,7 @@ import { persistReducer } from 'redux-persist';
|
|||
|
||||
// tslint:disable-next-line: no-submodule-imports match-default-export-name
|
||||
import storage from 'redux-persist/lib/storage';
|
||||
import purgeStoredState from 'redux-persist/es/purgeStoredState';
|
||||
|
||||
// @ts-ignore
|
||||
const env = window.getEnvironment();
|
||||
|
@ -26,10 +27,10 @@ const logger = createLogger({
|
|||
logger: directConsole,
|
||||
});
|
||||
|
||||
const persistConfig = {
|
||||
export const persistConfig = {
|
||||
key: 'root',
|
||||
storage,
|
||||
whitelist: ['userConfig'],
|
||||
whitelist: ['userConfig', 'conversations'],
|
||||
};
|
||||
|
||||
const persistedReducer = persistReducer(persistConfig, allReducers);
|
||||
|
|
|
@ -82,6 +82,7 @@ export interface ConversationType {
|
|||
avatarPath?: string; // absolute filepath to the avatar
|
||||
groupAdmins?: Array<string>; // admins for closed groups and moderators for open groups
|
||||
members?: Array<string>; // members for closed groups only
|
||||
isPinned?: boolean
|
||||
}
|
||||
|
||||
export type ConversationLookupType = {
|
||||
|
|
Loading…
Reference in a new issue