Merge pull request #1277 from Bilb/fix-blocklist-handle
commit
eb06356b26
@ -1,69 +0,0 @@
|
||||
/* global Whisper, Signal, Backbone */
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
// list of conversations, showing user/group and last message sent
|
||||
Whisper.ConversationListItemView = Whisper.View.extend({
|
||||
tagName: 'div',
|
||||
className() {
|
||||
return `conversation-list-item contact ${this.model.cid}`;
|
||||
},
|
||||
templateName: 'conversation-preview',
|
||||
initialize() {
|
||||
this.listenTo(this.model, 'destroy', this.remove);
|
||||
},
|
||||
|
||||
remove() {
|
||||
if (this.childView) {
|
||||
this.childView.remove();
|
||||
this.childView = null;
|
||||
}
|
||||
Backbone.View.prototype.remove.call(this);
|
||||
},
|
||||
|
||||
getProps() {
|
||||
return this.model.getPropsForListItem();
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.childView) {
|
||||
this.childView.remove();
|
||||
this.childView = null;
|
||||
}
|
||||
|
||||
const props = this.getProps();
|
||||
this.childView = new Whisper.ReactWrapperView({
|
||||
className: 'list-item-wrapper',
|
||||
Component: Signal.Components.ConversationListItem,
|
||||
props,
|
||||
});
|
||||
|
||||
const update = () => this.childView.update(this.getProps());
|
||||
|
||||
this.listenTo(this.model, 'change', update);
|
||||
|
||||
this.$el.append(this.childView.el);
|
||||
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
// list of conversations, showing user/group and last message sent
|
||||
Whisper.ConversationContactListItemView = Whisper.ConversationListItemView.extend(
|
||||
{
|
||||
getProps() {
|
||||
// We don't want to show a timestamp or a message
|
||||
const props = this.model.getPropsForListItem();
|
||||
delete props.lastMessage;
|
||||
delete props.lastUpdated;
|
||||
delete props.isSelected;
|
||||
|
||||
return props;
|
||||
},
|
||||
}
|
||||
);
|
||||
})();
|
@ -1,71 +0,0 @@
|
||||
/* global Whisper, getInboxCollection, $ */
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
Whisper.ConversationListView = Whisper.ListView.extend({
|
||||
tagName: 'div',
|
||||
itemView: Whisper.ConversationListItemView,
|
||||
getCollection() {
|
||||
return getInboxCollection();
|
||||
},
|
||||
updateLocation(conversation) {
|
||||
const $el = this.$(`.${conversation.cid}`);
|
||||
|
||||
if (!$el || !$el.length) {
|
||||
window.log.warn(
|
||||
'updateLocation: did not find element for conversation',
|
||||
conversation.idForLogging()
|
||||
);
|
||||
return;
|
||||
}
|
||||
if ($el.length > 1) {
|
||||
window.log.warn(
|
||||
'updateLocation: found more than one element for conversation',
|
||||
conversation.idForLogging()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const $allConversations = this.$('.conversation-list-item');
|
||||
const inboxCollection = this.getCollection();
|
||||
const index = inboxCollection.indexOf(conversation);
|
||||
|
||||
const elIndex = $allConversations.index($el);
|
||||
if (elIndex < 0) {
|
||||
window.log.warn(
|
||||
'updateLocation: did not find index for conversation',
|
||||
conversation.idForLogging()
|
||||
);
|
||||
}
|
||||
|
||||
if (index === elIndex) {
|
||||
return;
|
||||
}
|
||||
if (index === 0) {
|
||||
this.$el.prepend($el);
|
||||
} else if (index === this.collection.length - 1) {
|
||||
this.$el.append($el);
|
||||
} else {
|
||||
const targetConversation = inboxCollection.at(index - 1);
|
||||
const target = this.$(`.${targetConversation.cid}`);
|
||||
$el.insertAfter(target);
|
||||
}
|
||||
|
||||
if ($('.selected').length) {
|
||||
$('.selected')[0].scrollIntoView({
|
||||
block: 'nearest',
|
||||
});
|
||||
}
|
||||
},
|
||||
removeItem(conversation) {
|
||||
const $el = this.$(`.${conversation.cid}`);
|
||||
if ($el && $el.length > 0) {
|
||||
$el.remove();
|
||||
}
|
||||
},
|
||||
});
|
||||
})();
|
@ -1,177 +0,0 @@
|
||||
/* global ConversationController, i18n, textsecure, Whisper */
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
const isSearchable = conversation => conversation.isSearchable();
|
||||
|
||||
Whisper.NewContactView = Whisper.View.extend({
|
||||
templateName: 'new-contact',
|
||||
className: 'conversation-list-item contact',
|
||||
events: {
|
||||
click: 'validate',
|
||||
},
|
||||
initialize() {
|
||||
this.listenTo(this.model, 'change', this.render); // auto update
|
||||
},
|
||||
render_attributes() {
|
||||
// Show the appropriate message based on model validity
|
||||
const message =
|
||||
this.model && this.model.isValid()
|
||||
? i18n('startConversation')
|
||||
: i18n('invalidNumberError');
|
||||
return {
|
||||
number: message,
|
||||
title: this.model.getNumber(),
|
||||
avatar: this.model.getAvatar(),
|
||||
};
|
||||
},
|
||||
validate() {
|
||||
if (this.model.isValid()) {
|
||||
this.$el.addClass('valid');
|
||||
} else {
|
||||
this.$el.removeClass('valid');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Whisper.ConversationSearchView = Whisper.View.extend({
|
||||
className: 'conversation-search',
|
||||
initialize(options) {
|
||||
this.$input = options.input;
|
||||
this.$new_contact = this.$('.new-contact');
|
||||
|
||||
this.typeahead = new Whisper.ConversationCollection();
|
||||
this.collection = new Whisper.ConversationCollection([], {
|
||||
comparator(m) {
|
||||
return m.getTitle().toLowerCase();
|
||||
},
|
||||
});
|
||||
this.listenTo(this.collection, 'select', conversation => {
|
||||
this.resetTypeahead();
|
||||
this.trigger('open', conversation);
|
||||
});
|
||||
|
||||
// View to display the matched contacts from typeahead
|
||||
this.typeahead_view = new Whisper.ConversationListView({
|
||||
collection: this.collection,
|
||||
});
|
||||
this.$el.append(this.typeahead_view.el);
|
||||
this.initNewContact();
|
||||
this.pending = Promise.resolve();
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .new-contact': 'createConversation',
|
||||
},
|
||||
|
||||
filterContacts() {
|
||||
const query = this.$input.val().trim();
|
||||
if (query.length) {
|
||||
// Update the contact model
|
||||
this.new_contact_view.model.set('id', query);
|
||||
this.new_contact_view.render().$el.hide();
|
||||
this.new_contact_view.validate();
|
||||
this.hideHints();
|
||||
|
||||
// NOTE: Temporarily allow `then` until we convert the entire file
|
||||
// to `async` / `await`:
|
||||
/* eslint-disable more/no-then */
|
||||
this.pending = this.pending.then(() =>
|
||||
this.typeahead.search(query).then(() => {
|
||||
let results = this.typeahead.filter(isSearchable);
|
||||
const noteToSelf = i18n('noteToSelf');
|
||||
if (noteToSelf.toLowerCase().indexOf(query.toLowerCase()) !== -1) {
|
||||
const ourNumber = textsecure.storage.user.getNumber();
|
||||
const conversation = ConversationController.get(ourNumber);
|
||||
if (conversation) {
|
||||
// ensure that we don't have duplicates in our results
|
||||
results = results.filter(item => item.id !== ourNumber);
|
||||
results.unshift(conversation);
|
||||
}
|
||||
}
|
||||
|
||||
this.typeahead_view.collection.reset(results);
|
||||
|
||||
// This will allow us to show the last message when searching
|
||||
this.typeahead_view.collection.forEach(c => c.updateLastMessage());
|
||||
|
||||
// Show the new contact view if we already have results
|
||||
if (this.typeahead_view.collection.length === 0) {
|
||||
this.new_contact_view.$el.show();
|
||||
}
|
||||
})
|
||||
);
|
||||
/* eslint-enable more/no-then */
|
||||
this.trigger('show');
|
||||
} else {
|
||||
this.resetTypeahead();
|
||||
}
|
||||
},
|
||||
|
||||
initNewContact() {
|
||||
if (this.new_contact_view) {
|
||||
this.new_contact_view.undelegateEvents();
|
||||
this.new_contact_view.$el.hide();
|
||||
}
|
||||
const model = new Whisper.Conversation({ type: 'private' });
|
||||
this.new_contact_view = new Whisper.NewContactView({
|
||||
el: this.$new_contact,
|
||||
model,
|
||||
}).render();
|
||||
},
|
||||
|
||||
async createConversation() {
|
||||
const isValidNumber = this.new_contact_view.model.isValid();
|
||||
if (!isValidNumber) {
|
||||
this.$input.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
const newConversationId = this.new_contact_view.model.id;
|
||||
const conversation = await ConversationController.getOrCreateAndWait(
|
||||
newConversationId,
|
||||
'private'
|
||||
);
|
||||
this.trigger('open', conversation);
|
||||
this.initNewContact();
|
||||
this.resetTypeahead();
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.delegateEvents();
|
||||
this.typeahead_view.delegateEvents();
|
||||
this.new_contact_view.delegateEvents();
|
||||
this.resetTypeahead();
|
||||
},
|
||||
|
||||
resetTypeahead() {
|
||||
this.hideHints();
|
||||
this.new_contact_view.$el.hide();
|
||||
this.$input.val('').focus();
|
||||
this.typeahead_view.collection.reset([]);
|
||||
this.trigger('hide');
|
||||
},
|
||||
|
||||
showHints() {
|
||||
if (!this.hintView) {
|
||||
this.hintView = new Whisper.HintView({
|
||||
className: 'contact placeholder',
|
||||
content: i18n('newPhoneNumber'),
|
||||
}).render();
|
||||
this.hintView.$el.insertAfter(this.$input);
|
||||
}
|
||||
this.hintView.$el.show();
|
||||
},
|
||||
|
||||
hideHints() {
|
||||
if (this.hintView) {
|
||||
this.hintView.remove();
|
||||
this.hintView = null;
|
||||
}
|
||||
},
|
||||
});
|
||||
})();
|
@ -1,67 +0,0 @@
|
||||
/* global $, Whisper */
|
||||
|
||||
describe('ConversationSearchView', () => {
|
||||
describe('Searching for left groups', () => {
|
||||
let convo;
|
||||
|
||||
before(() => {
|
||||
convo = new Whisper.ConversationCollection().add({
|
||||
id: '1-search-view',
|
||||
name: 'i left this group',
|
||||
members: [],
|
||||
type: 'group',
|
||||
left: true,
|
||||
});
|
||||
|
||||
return window.Signal.Data.saveConversation(convo.attributes, {
|
||||
Conversation: Whisper.Conversation,
|
||||
});
|
||||
});
|
||||
describe('with no messages', () => {
|
||||
let input;
|
||||
let view;
|
||||
|
||||
before(done => {
|
||||
input = $('<input>');
|
||||
view = new Whisper.ConversationSearchView({ input }).render();
|
||||
view.$input.val('left');
|
||||
view.filterContacts();
|
||||
view.typeahead_view.collection.on('reset', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should not surface left groups with no messages', () => {
|
||||
assert.isUndefined(
|
||||
view.typeahead_view.collection.get(convo.id),
|
||||
'got left group'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('with messages', () => {
|
||||
let input;
|
||||
let view;
|
||||
before(async () => {
|
||||
input = $('<input>');
|
||||
view = new Whisper.ConversationSearchView({ input }).render();
|
||||
convo.set({ id: '2-search-view', left: false });
|
||||
|
||||
await window.Signal.Data.saveConversation(convo.attributes, {
|
||||
Conversation: Whisper.Conversation,
|
||||
});
|
||||
|
||||
view.$input.val('left');
|
||||
view.filterContacts();
|
||||
|
||||
return new Promise(resolve => {
|
||||
view.typeahead_view.collection.on('reset', resolve);
|
||||
});
|
||||
});
|
||||
it('should surface left groups with messages', () => {
|
||||
assert.isDefined(
|
||||
view.typeahead_view.collection.get(convo.id),
|
||||
'got left group'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,43 @@
|
||||
import { SyncMessage } from './SyncMessage';
|
||||
import { SignalService } from '../../../../../protobuf';
|
||||
import { MessageParams } from '../../Message';
|
||||
import { StringUtils } from '../../../../utils';
|
||||
|
||||
interface BlockedListSyncMessageParams extends MessageParams {
|
||||
groups: Array<string>;
|
||||
numbers: Array<string>;
|
||||
}
|
||||
|
||||
export abstract class BlockedListSyncMessage extends SyncMessage {
|
||||
public readonly groups: Array<Uint8Array>;
|
||||
public readonly numbers: Array<string>;
|
||||
|
||||
constructor(params: BlockedListSyncMessageParams) {
|
||||
super({ timestamp: params.timestamp, identifier: params.identifier });
|
||||
this.groups = params.groups.map(g => {
|
||||
if (typeof g !== 'string') {
|
||||
throw new TypeError(
|
||||
`invalid group id (expected string) found:${typeof g}`
|
||||
);
|
||||
}
|
||||
return new Uint8Array(StringUtils.encode(g, 'utf8'));
|
||||
});
|
||||
if (params.numbers.length && typeof params.numbers[0] !== 'string') {
|
||||
throw new TypeError(
|
||||
`invalid number (expected string) found:${typeof params.numbers[0]}`
|
||||
);
|
||||
}
|
||||
this.numbers = params.numbers;
|
||||
}
|
||||
|
||||
protected syncProto(): SignalService.SyncMessage {
|
||||
const syncMessage = super.syncProto();
|
||||
// currently we do not handle the closed group blocked
|
||||
syncMessage.blocked = new SignalService.SyncMessage.Blocked({
|
||||
numbers: this.numbers,
|
||||
groupIds: this.groups,
|
||||
});
|
||||
|
||||
return syncMessage;
|
||||
}
|
||||
}
|
@ -0,0 +1,336 @@
|
||||
import React from 'react';
|
||||
import { MenuItem, SubMenu } from 'react-contextmenu';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { TimerOption } from '../../components/conversation/ConversationHeader';
|
||||
|
||||
function showTimerOptions(
|
||||
isPublic: boolean,
|
||||
isRss: boolean,
|
||||
isKickedFromGroup: boolean,
|
||||
isBlocked: boolean
|
||||
): boolean {
|
||||
return (
|
||||
Boolean(!isPublic) && Boolean(!isRss) && !isKickedFromGroup && !isBlocked
|
||||
);
|
||||
}
|
||||
|
||||
function showMemberMenu(
|
||||
isPublic: boolean,
|
||||
isRss: boolean,
|
||||
isGroup: boolean
|
||||
): boolean {
|
||||
return Boolean(!isPublic) && Boolean(!isRss) && isGroup;
|
||||
}
|
||||
|
||||
function showSafetyNumber(
|
||||
isPublic: boolean,
|
||||
isRss: boolean,
|
||||
isGroup: boolean,
|
||||
isMe: boolean
|
||||
): boolean {
|
||||
return Boolean(!isPublic) && Boolean(!isRss) && !isGroup && !isMe;
|
||||
}
|
||||
|
||||
function showResetSession(
|
||||
isPublic: boolean,
|
||||
isRss: boolean,
|
||||
isGroup: boolean
|
||||
): boolean {
|
||||
return Boolean(!isPublic) && Boolean(!isRss) && Boolean(!isGroup);
|
||||
}
|
||||
|
||||
function showBlock(
|
||||
isMe: boolean | undefined,
|
||||
isPrivate: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(!isMe) && Boolean(isPrivate);
|
||||
}
|
||||
|
||||
function showClearNickname(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isMe: boolean | undefined,
|
||||
hasNickname: boolean | undefined
|
||||
): boolean {
|
||||
return (
|
||||
Boolean(!isPublic) &&
|
||||
Boolean(!isRss) &&
|
||||
Boolean(!isMe) &&
|
||||
Boolean(hasNickname)
|
||||
);
|
||||
}
|
||||
|
||||
function showCopyId(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(!isPublic) && Boolean(!isRss);
|
||||
}
|
||||
|
||||
function showDeleteContact(
|
||||
isMe: boolean | undefined,
|
||||
isClosable: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined
|
||||
): boolean {
|
||||
return (
|
||||
Boolean(!isMe) && Boolean(isClosable) && !!(!isGroup || isPublic || isRss)
|
||||
);
|
||||
}
|
||||
|
||||
function showAddModerators(
|
||||
amMod: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(!isKickedFromGroup) && Boolean(amMod);
|
||||
}
|
||||
|
||||
function showRemoveModerators(
|
||||
amMod: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(!isKickedFromGroup) && Boolean(amMod);
|
||||
}
|
||||
|
||||
function showUpdateGroupName(
|
||||
amMod: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(!isKickedFromGroup) && Boolean(amMod);
|
||||
}
|
||||
|
||||
function showLeaveGroup(
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(!isKickedFromGroup) && Boolean(isGroup) && !isPublic && !isRss;
|
||||
}
|
||||
|
||||
function showInviteContact(
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined
|
||||
): boolean {
|
||||
return Boolean(isGroup) && Boolean(isPublic);
|
||||
}
|
||||
|
||||
/** Menu items standardized */
|
||||
|
||||
export function getInviteContactMenuItem(
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showInviteContact(isGroup, isPublic)) {
|
||||
return <MenuItem onClick={action}>{i18n('inviteContacts')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getDeleteContactMenuItem(
|
||||
isMe: boolean | undefined,
|
||||
isClosable: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showDeleteContact(isMe, isClosable, isGroup, isPublic, isRss)) {
|
||||
if (isPublic) {
|
||||
return (
|
||||
<MenuItem onClick={action}>{i18n('deletePublicChannel')}</MenuItem>
|
||||
);
|
||||
}
|
||||
return <MenuItem onClick={action}>{i18n('deleteContact')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getLeaveGroupMenuItem(
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showLeaveGroup(isKickedFromGroup, isGroup, isPublic, isRss)) {
|
||||
return <MenuItem onClick={action}>{i18n('leaveGroup')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getUpdateGroupNameMenuItem(
|
||||
amMod: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showUpdateGroupName(amMod, isKickedFromGroup)) {
|
||||
return (
|
||||
<MenuItem onClick={action}>{i18n('editGroupNameOrPicture')}</MenuItem>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getRemoveModeratorsMenuItem(
|
||||
amMod: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showRemoveModerators(amMod, isKickedFromGroup)) {
|
||||
return <MenuItem onClick={action}>{i18n('removeModerators')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getAddModeratorsMenuItem(
|
||||
amMod: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showAddModerators(amMod, isKickedFromGroup)) {
|
||||
return <MenuItem onClick={action}>{i18n('addModerators')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getCopyIdMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showCopyId(isPublic, isRss)) {
|
||||
const copyIdLabel = isGroup ? i18n('copyChatId') : i18n('copyPublicKey');
|
||||
return <MenuItem onClick={action}>{copyIdLabel}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getDisappearingMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
isBlocked: boolean | undefined,
|
||||
timerOptions: Array<TimerOption>,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (
|
||||
showTimerOptions(
|
||||
Boolean(isPublic),
|
||||
Boolean(isRss),
|
||||
Boolean(isKickedFromGroup),
|
||||
Boolean(isBlocked)
|
||||
)
|
||||
) {
|
||||
return (
|
||||
<SubMenu title={i18n('disappearingMessages') as any}>
|
||||
{(timerOptions || []).map(item => (
|
||||
<MenuItem
|
||||
key={item.value}
|
||||
onClick={() => {
|
||||
action(item.value);
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</SubMenu>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getShowMemberMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showMemberMenu(Boolean(isPublic), Boolean(isRss), Boolean(isGroup))) {
|
||||
return <MenuItem onClick={action}>{i18n('showMembers')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getShowSafetyNumberMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
isMe: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (
|
||||
showSafetyNumber(
|
||||
Boolean(isPublic),
|
||||
Boolean(isRss),
|
||||
Boolean(isGroup),
|
||||
Boolean(isMe)
|
||||
)
|
||||
) {
|
||||
return <MenuItem onClick={action}>{i18n('showSafetyNumber')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getResetSessionMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showResetSession(Boolean(isPublic), Boolean(isRss), Boolean(isGroup))) {
|
||||
return <MenuItem onClick={action}>{i18n('resetSession')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getBlockMenuItem(
|
||||
isMe: boolean | undefined,
|
||||
isPrivate: boolean | undefined,
|
||||
isBlocked: boolean | undefined,
|
||||
actionBlock: any,
|
||||
actionUnblock: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (showBlock(Boolean(isMe), Boolean(isPrivate))) {
|
||||
const blockTitle = isBlocked ? i18n('unblockUser') : i18n('blockUser');
|
||||
const blockHandler = isBlocked ? actionUnblock : actionBlock;
|
||||
return <MenuItem onClick={blockHandler}>{blockTitle}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getClearNicknameMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isRss: boolean | undefined,
|
||||
isMe: boolean | undefined,
|
||||
hasNickname: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
): JSX.Element | null {
|
||||
if (
|
||||
showClearNickname(
|
||||
Boolean(isPublic),
|
||||
Boolean(isRss),
|
||||
Boolean(isMe),
|
||||
Boolean(hasNickname)
|
||||
)
|
||||
) {
|
||||
return <MenuItem onClick={action}>{i18n('clearNickname')}</MenuItem>;
|
||||
}
|
||||
return null;
|
||||
}
|
Loading…
Reference in New Issue