Some improvements
This commit is contained in:
parent
14a2714c1e
commit
c53eefaf6d
19 changed files with 205 additions and 70 deletions
|
@ -5727,6 +5727,14 @@
|
|||
"messageformat": "To change this setting, open the Signal app on your mobile device and navigate to Settings > Chats",
|
||||
"description": "Description for the generate link previews setting"
|
||||
},
|
||||
"icu:Preferences__auto-convert-emoji--title": {
|
||||
"messageformat": "Convert typed emoticons to emoji",
|
||||
"description": "Title for the auto convert emoji setting"
|
||||
},
|
||||
"icu:Preferences__auto-convert-emoji--description": {
|
||||
"messageformat": "For example, :-) will be converted to 🙂",
|
||||
"description": "Description for the auto convert emoji setting"
|
||||
},
|
||||
"icu:Preferences--advanced": {
|
||||
"messageformat": "Advanced",
|
||||
"description": "Title for advanced settings"
|
||||
|
|
|
@ -972,6 +972,14 @@ export async function startApp(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
window.storage.get('autoConvertEmoji') === undefined &&
|
||||
newVersion &&
|
||||
!lastVersion
|
||||
) {
|
||||
await window.storage.put('autoConvertEmoji', true);
|
||||
}
|
||||
|
||||
setAppLoadingScreenMessage(
|
||||
window.i18n('icu:optimizingApplication'),
|
||||
window.i18n
|
||||
|
|
|
@ -5,6 +5,7 @@ import React, { forwardRef, useMemo } from 'react';
|
|||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { getClassNamesFor } from '../util/getClassNamesFor';
|
||||
import { Emojify } from './conversation/Emojify';
|
||||
|
||||
export type PropsType = {
|
||||
checked?: boolean;
|
||||
|
@ -61,7 +62,9 @@ export const Checkbox = forwardRef(function CheckboxInner(
|
|||
<div>
|
||||
<label htmlFor={id}>
|
||||
<div>{label}</div>
|
||||
<div className={getClassName('__description')}>{description}</div>
|
||||
<div className={getClassName('__description')}>
|
||||
<Emojify text={description ?? ''} />
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -39,7 +39,9 @@ import {
|
|||
getDeltaToRemoveStaleMentions,
|
||||
getTextAndRangesFromOps,
|
||||
isMentionBlot,
|
||||
isEmojiBlot,
|
||||
getDeltaToRestartMention,
|
||||
getDeltaToRestartEmoji,
|
||||
insertEmojiOps,
|
||||
insertFormattingAndMentionsOps,
|
||||
} from '../quill/util';
|
||||
|
@ -284,7 +286,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const delta = new Delta()
|
||||
.retain(insertionRange.index)
|
||||
.delete(insertionRange.length)
|
||||
.insert({ emoji });
|
||||
.insert({ emoji: { value: emoji } });
|
||||
|
||||
quill.updateContents(delta, 'user');
|
||||
quill.setSelection(insertionRange.index + 1, 0, 'user');
|
||||
|
@ -512,17 +514,24 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
}
|
||||
|
||||
const [blotToDelete] = quill.getLeaf(selection.index);
|
||||
if (!isMentionBlot(blotToDelete)) {
|
||||
return true;
|
||||
if (isMentionBlot(blotToDelete)) {
|
||||
const contents = quill.getContents(0, selection.index - 1);
|
||||
const restartDelta = getDeltaToRestartMention(contents.ops);
|
||||
|
||||
quill.updateContents(restartDelta);
|
||||
quill.setSelection(selection.index, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
const contents = quill.getContents(0, selection.index - 1);
|
||||
const restartDelta = getDeltaToRestartMention(contents.ops);
|
||||
if (isEmojiBlot(blotToDelete)) {
|
||||
const contents = quill.getContents(0, selection.index);
|
||||
const restartDelta = getDeltaToRestartEmoji(contents.ops);
|
||||
|
||||
quill.updateContents(restartDelta);
|
||||
quill.setSelection(selection.index, 0);
|
||||
quill.updateContents(restartDelta);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
const onChange = (): void => {
|
||||
|
@ -731,7 +740,9 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
callbacksRef.current.onPickEmoji(emoji),
|
||||
skinTone,
|
||||
},
|
||||
autoSubstituteAsciiEmojis: true,
|
||||
autoSubstituteAsciiEmojis: {
|
||||
skinTone,
|
||||
},
|
||||
formattingMenu: {
|
||||
i18n,
|
||||
isMenuEnabled: isFormattingEnabled,
|
||||
|
|
|
@ -76,6 +76,7 @@ export default {
|
|||
defaultConversationColor: DEFAULT_CONVERSATION_COLOR,
|
||||
deviceName: 'Work Windows ME',
|
||||
hasAudioNotifications: true,
|
||||
hasAutoConvertEmoji: true,
|
||||
hasAutoDownloadUpdate: true,
|
||||
hasAutoLaunch: true,
|
||||
hasCallNotifications: true,
|
||||
|
@ -133,6 +134,7 @@ export default {
|
|||
executeMenuRole: action('executeMenuRole'),
|
||||
makeSyncRequest: action('makeSyncRequest'),
|
||||
onAudioNotificationsChange: action('onAudioNotificationsChange'),
|
||||
onAutoConvertEmojiChange: action('onAutoConvertEmojiChange'),
|
||||
onAutoDownloadUpdateChange: action('onAutoDownloadUpdateChange'),
|
||||
onAutoLaunchChange: action('onAutoLaunchChange'),
|
||||
onCallNotificationsChange: action('onCallNotificationsChange'),
|
||||
|
|
|
@ -75,6 +75,7 @@ export type PropsDataType = {
|
|||
defaultConversationColor: DefaultConversationColorType;
|
||||
deviceName?: string;
|
||||
hasAudioNotifications?: boolean;
|
||||
hasAutoConvertEmoji: boolean;
|
||||
hasAutoDownloadUpdate: boolean;
|
||||
hasAutoLaunch: boolean;
|
||||
hasCallNotifications: boolean;
|
||||
|
@ -159,6 +160,7 @@ type PropsFunctionType = {
|
|||
|
||||
// Change handlers
|
||||
onAudioNotificationsChange: CheckboxChangeHandlerType;
|
||||
onAutoConvertEmojiChange: CheckboxChangeHandlerType;
|
||||
onAutoDownloadUpdateChange: CheckboxChangeHandlerType;
|
||||
onAutoLaunchChange: CheckboxChangeHandlerType;
|
||||
onCallNotificationsChange: CheckboxChangeHandlerType;
|
||||
|
@ -257,6 +259,7 @@ export function Preferences({
|
|||
executeMenuRole,
|
||||
getConversationsWithCustomColor,
|
||||
hasAudioNotifications,
|
||||
hasAutoConvertEmoji,
|
||||
hasAutoDownloadUpdate,
|
||||
hasAutoLaunch,
|
||||
hasCallNotifications,
|
||||
|
@ -293,6 +296,7 @@ export function Preferences({
|
|||
makeSyncRequest,
|
||||
notificationContent,
|
||||
onAudioNotificationsChange,
|
||||
onAutoConvertEmojiChange,
|
||||
onAutoDownloadUpdateChange,
|
||||
onAutoLaunchChange,
|
||||
onCallNotificationsChange,
|
||||
|
@ -856,6 +860,16 @@ export function Preferences({
|
|||
name="linkPreviews"
|
||||
onChange={noop}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={hasAutoConvertEmoji}
|
||||
description={i18n(
|
||||
'icu:Preferences__auto-convert-emoji--description'
|
||||
)}
|
||||
label={i18n('icu:Preferences__auto-convert-emoji--title')}
|
||||
moduleClassName="Preferences__checkbox"
|
||||
name="autoConvertEmoji"
|
||||
onChange={onAutoConvertEmojiChange}
|
||||
/>
|
||||
<Control
|
||||
left={i18n('icu:Preferences__sent-media-quality')}
|
||||
right={
|
||||
|
|
|
@ -93,6 +93,7 @@ export class SettingsChannel extends EventEmitter {
|
|||
});
|
||||
this.installSetting('textFormatting');
|
||||
|
||||
this.installSetting('autoConvertEmoji');
|
||||
this.installSetting('autoDownloadUpdate');
|
||||
this.installSetting('autoLaunch');
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import type Quill from 'quill';
|
||||
import Delta from 'quill-delta';
|
||||
import _ from 'lodash';
|
||||
import type { EmojiData } from '../../components/emoji/lib';
|
||||
import {
|
||||
convertShortName,
|
||||
|
@ -15,32 +14,34 @@ type AutoSubstituteAsciiEmojisOptions = {
|
|||
};
|
||||
|
||||
const emojiMap: Record<string, string> = {
|
||||
':)': 'slightly_smiling_face',
|
||||
':-)': 'slightly_smiling_face',
|
||||
':(': 'slightly_frowning_face',
|
||||
':-(': 'slightly_frowning_face',
|
||||
':D': 'smiley',
|
||||
':-D': 'smiley',
|
||||
':*': 'kissing',
|
||||
':-*': 'kissing',
|
||||
':P': 'stuck_out_tongue',
|
||||
':-D': 'grinning',
|
||||
':-*': 'kissing_heart',
|
||||
':-P': 'stuck_out_tongue',
|
||||
';P': 'stuck_out_tongue_winking_eye',
|
||||
';-P': 'stuck_out_tongue_winking_eye',
|
||||
'D:': 'anguished',
|
||||
"D-':": 'anguished',
|
||||
':O': 'open_mouth',
|
||||
':-O': 'open_mouth',
|
||||
':-p': 'stuck_out_tongue',
|
||||
":'(": 'cry',
|
||||
":'-(": 'cry',
|
||||
':/': 'confused',
|
||||
':-/': 'confused',
|
||||
';)': 'wink',
|
||||
':-\\': 'confused',
|
||||
';-)': 'wink',
|
||||
'(Y)': '+1',
|
||||
'(N)': '-1',
|
||||
'(y)': '+1',
|
||||
'(n)': '-1',
|
||||
'<3': 'heart',
|
||||
'^_^': 'grin',
|
||||
'>_<': 'laughing',
|
||||
};
|
||||
|
||||
function buildRegexp(obj: Record<string, string>): RegExp {
|
||||
const sanitizedKeys = Object.keys(obj).map(x =>
|
||||
x.replace(/([^a-zA-Z0-9])/g, '\\$1')
|
||||
);
|
||||
|
||||
return new RegExp(`(${sanitizedKeys.join('|')})$`);
|
||||
}
|
||||
|
||||
const EMOJI_REGEXP = buildRegexp(emojiMap);
|
||||
|
||||
export class AutoSubstituteAsciiEmojis {
|
||||
options: AutoSubstituteAsciiEmojisOptions;
|
||||
|
||||
|
@ -50,13 +51,24 @@ export class AutoSubstituteAsciiEmojis {
|
|||
this.options = options;
|
||||
this.quill = quill;
|
||||
|
||||
this.quill.on(
|
||||
'text-change',
|
||||
_.debounce(() => this.onTextChange(), 100)
|
||||
);
|
||||
this.quill.on('text-change', (_now, _before, source) => {
|
||||
if (source !== 'user') {
|
||||
return;
|
||||
}
|
||||
|
||||
// When pasting - Quill first updates contents with "user" source and only
|
||||
// then updates the selection with "silent" source. This means that unless
|
||||
// we wrap `onTextChange` with setTimeout - we are not going to see the
|
||||
// updated cursor position.
|
||||
setTimeout(() => this.onTextChange(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
onTextChange(): void {
|
||||
if (!window.storage.get('autoConvertEmoji', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const range = this.quill.getSelection();
|
||||
|
||||
if (!range) {
|
||||
|
@ -65,32 +77,44 @@ export class AutoSubstituteAsciiEmojis {
|
|||
|
||||
const [blot, index] = this.quill.getLeaf(range.index);
|
||||
|
||||
if (blot !== undefined && blot.text !== undefined) {
|
||||
const blotText: string = blot.text;
|
||||
Object.entries(emojiMap).some(([textEmoji, emojiName]) => {
|
||||
if (blotText.substring(0, index).endsWith(textEmoji)) {
|
||||
const emojiData = convertShortNameToData(
|
||||
emojiName,
|
||||
this.options.skinTone
|
||||
);
|
||||
if (emojiData) {
|
||||
this.insertEmoji(
|
||||
emojiData,
|
||||
range.index - textEmoji.length,
|
||||
textEmoji.length
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (blot?.text == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const textBeforeCursor = blot.text.slice(0, index);
|
||||
const match = textBeforeCursor.match(EMOJI_REGEXP);
|
||||
if (match == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [, textEmoji] = match;
|
||||
const emojiName = emojiMap[textEmoji];
|
||||
|
||||
const emojiData = convertShortNameToData(emojiName, this.options.skinTone);
|
||||
if (emojiData) {
|
||||
this.insertEmoji(
|
||||
emojiData,
|
||||
range.index - textEmoji.length,
|
||||
textEmoji.length,
|
||||
textEmoji
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
insertEmoji(emojiData: EmojiData, index: number, range: number): void {
|
||||
insertEmoji(
|
||||
emojiData: EmojiData,
|
||||
index: number,
|
||||
range: number,
|
||||
source: string
|
||||
): void {
|
||||
const emoji = convertShortName(emojiData.short_name, this.options.skinTone);
|
||||
const delta = new Delta().retain(index).delete(range).insert({ emoji });
|
||||
this.quill.updateContents(delta, 'user');
|
||||
const delta = new Delta()
|
||||
.retain(index)
|
||||
.delete(range)
|
||||
.insert({
|
||||
emoji: { value: emoji, source },
|
||||
});
|
||||
this.quill.updateContents(delta, 'api');
|
||||
this.quill.setSelection(index + 1, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@ const Embed: typeof Parchment.Embed = Quill.import('blots/embed');
|
|||
// ts/components/conversation/Emojify.tsx
|
||||
// ts/components/emoji/Emoji.tsx
|
||||
|
||||
export type EmojiBlotValue = Readonly<{
|
||||
value: string;
|
||||
source?: string;
|
||||
}>;
|
||||
|
||||
export class EmojiBlot extends Embed {
|
||||
static override blotName = 'emoji';
|
||||
|
||||
|
@ -19,21 +24,30 @@ export class EmojiBlot extends Embed {
|
|||
|
||||
static override className = 'emoji-blot';
|
||||
|
||||
static override create(emoji: string): Node {
|
||||
static override create({ value: emoji, source }: EmojiBlotValue): Node {
|
||||
const node = super.create(undefined) as HTMLElement;
|
||||
node.dataset.emoji = emoji;
|
||||
node.dataset.source = source;
|
||||
|
||||
const image = emojiToImage(emoji);
|
||||
|
||||
node.setAttribute('src', image || '');
|
||||
node.setAttribute('data-emoji', emoji);
|
||||
node.setAttribute('data-source', source || '');
|
||||
node.setAttribute('title', emoji);
|
||||
node.setAttribute('aria-label', emoji);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static override value(node: HTMLElement): string | undefined {
|
||||
return node.dataset.emoji;
|
||||
static override value(node: HTMLElement): EmojiBlotValue | undefined {
|
||||
const { emoji, source } = node.dataset;
|
||||
if (emoji === undefined) {
|
||||
throw new Error(
|
||||
`Failed to make EmojiBlot with emoji: ${emoji}, source: ${source}`
|
||||
);
|
||||
}
|
||||
|
||||
return { value: emoji, source };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,7 +247,12 @@ export class EmojiCompletion {
|
|||
): void {
|
||||
const emoji = convertShortName(emojiData.short_name, this.options.skinTone);
|
||||
|
||||
const delta = new Delta().retain(index).delete(range).insert({ emoji });
|
||||
const delta = new Delta()
|
||||
.retain(index)
|
||||
.delete(range)
|
||||
.insert({
|
||||
emoji: { value: emoji },
|
||||
});
|
||||
|
||||
if (withTrailingSpace) {
|
||||
// The extra space we add won't be formatted unless we manually provide attributes
|
||||
|
|
|
@ -15,8 +15,8 @@ export const matchEmojiImage: Matcher = (
|
|||
node.classList.contains('emoji') ||
|
||||
node.classList.contains('module-emoji__image--16px')
|
||||
) {
|
||||
const emoji = node.getAttribute('aria-label');
|
||||
return new Delta().insert({ emoji }, attributes);
|
||||
const value = node.getAttribute('aria-label');
|
||||
return new Delta().insert({ emoji: { value } }, attributes);
|
||||
}
|
||||
return delta;
|
||||
};
|
||||
|
@ -27,8 +27,8 @@ export const matchEmojiBlot: Matcher = (
|
|||
attributes: AttributeMap
|
||||
): Delta => {
|
||||
if (node.classList.contains('emoji-blot')) {
|
||||
const { emoji } = node.dataset;
|
||||
return new Delta().insert({ emoji }, attributes);
|
||||
const { emoji: value, source } = node.dataset;
|
||||
return new Delta().insert({ emoji: { value, source } }, attributes);
|
||||
}
|
||||
return delta;
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ import type {
|
|||
} from '../types/BodyRange';
|
||||
import { BodyRange } from '../types/BodyRange';
|
||||
import type { MentionBlot } from './mentions/blot';
|
||||
import type { EmojiBlot } from './emoji/blot';
|
||||
import { isNewlineOnlyOp, QuillFormattingStyle } from './formatting/menu';
|
||||
import { isNotNil } from '../util/isNotNil';
|
||||
import type { AciString } from '../types/ServiceId';
|
||||
|
@ -27,6 +28,9 @@ export type FormattingBlotValue = {
|
|||
style: BodyRange.Style;
|
||||
};
|
||||
|
||||
export const isEmojiBlot = (blot: LeafBlot): blot is EmojiBlot =>
|
||||
blot.value() && blot.value().emoji;
|
||||
|
||||
export const isMentionBlot = (blot: LeafBlot): blot is MentionBlot =>
|
||||
blot.value() && blot.value().mention;
|
||||
|
||||
|
@ -37,7 +41,10 @@ export type RetainOp = Op & { retain: number };
|
|||
export type InsertOp<K extends string, T> = Op & { insert: { [V in K]: T } };
|
||||
|
||||
export type InsertMentionOp = InsertOp<'mention', MentionBlotValue>;
|
||||
export type InsertEmojiOp = InsertOp<'emoji', string>;
|
||||
export type InsertEmojiOp = InsertOp<
|
||||
'emoji',
|
||||
{ value: string; source?: string }
|
||||
>;
|
||||
|
||||
export const isRetainOp = (op?: Op): op is RetainOp =>
|
||||
op !== undefined && op.retain !== undefined;
|
||||
|
@ -64,7 +71,7 @@ export const getTextFromOps = (ops: Array<DeltaOperation>): string =>
|
|||
}
|
||||
|
||||
if (isInsertEmojiOp(op)) {
|
||||
return acc + op.insert.emoji;
|
||||
return acc + op.insert.emoji.value;
|
||||
}
|
||||
|
||||
if (isInsertMentionOp(op)) {
|
||||
|
@ -187,7 +194,7 @@ export const getTextAndRangesFromOps = (
|
|||
}
|
||||
|
||||
if (isInsertEmojiOp(op)) {
|
||||
return acc + op.insert.emoji;
|
||||
return acc + op.insert.emoji.value;
|
||||
}
|
||||
|
||||
if (isInsertMentionOp(op)) {
|
||||
|
@ -304,6 +311,27 @@ export const getDeltaToRestartMention = (ops: Array<Op>): Delta => {
|
|||
return new Delta(changes);
|
||||
};
|
||||
|
||||
export const getDeltaToRestartEmoji = (ops: Array<Op>): Delta => {
|
||||
const changes = new Array<Op>();
|
||||
for (const op of ops.slice(0, -1)) {
|
||||
if (op.insert && typeof op.insert === 'string') {
|
||||
changes.push({ retain: op.insert.length });
|
||||
} else {
|
||||
changes.push({ retain: 1 });
|
||||
}
|
||||
}
|
||||
const last = ops.at(-1);
|
||||
if (!last || !last.insert) {
|
||||
throw new Error('No emoji to delete');
|
||||
}
|
||||
|
||||
changes.push({ delete: 1 });
|
||||
if ((last as InsertEmojiOp).insert.emoji?.source) {
|
||||
changes.push({ insert: (last as InsertEmojiOp).insert.emoji?.source });
|
||||
}
|
||||
return new Delta(changes);
|
||||
};
|
||||
|
||||
export const getDeltaToRemoveStaleMentions = (
|
||||
ops: Array<Op>,
|
||||
memberAcis: Array<AciString>
|
||||
|
@ -422,7 +450,7 @@ export const insertEmojiOps = (
|
|||
if (emojiData) {
|
||||
ops.push({ insert: text.slice(index, match.index), attributes });
|
||||
ops.push({
|
||||
insert: { emoji },
|
||||
insert: { emoji: { value: emoji } },
|
||||
attributes: { ...existingAttributes, ...attributes },
|
||||
});
|
||||
index = match.index + emoji.length;
|
||||
|
|
|
@ -59,12 +59,12 @@ describe('getDeltaToRemoveStaleMentions', () => {
|
|||
const originalOps = [
|
||||
{
|
||||
insert: {
|
||||
emoji: '😂',
|
||||
emoji: { value: '😂' },
|
||||
},
|
||||
},
|
||||
{
|
||||
insert: {
|
||||
emoji: '🍋',
|
||||
emoji: { value: '🍋' },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
@ -312,7 +312,7 @@ describe('getTextAndRangesFromOps', () => {
|
|||
const ops = [
|
||||
{
|
||||
insert: {
|
||||
emoji: '😂',
|
||||
emoji: { value: '😂' },
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -579,7 +579,7 @@ describe('getDeltaToRestartMention', () => {
|
|||
const originalOps = [
|
||||
{
|
||||
insert: {
|
||||
emoji: '😂',
|
||||
emoji: { value: '😂' },
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
1
ts/types/Storage.d.ts
vendored
1
ts/types/Storage.d.ts
vendored
|
@ -49,6 +49,7 @@ export type StorageAccessType = {
|
|||
'always-relay-calls': boolean;
|
||||
'audio-notification': boolean;
|
||||
'auto-download-update': boolean;
|
||||
autoConvertEmoji: boolean;
|
||||
'badge-count-muted-conversations': boolean;
|
||||
'blocked-groups': ReadonlyArray<string>;
|
||||
'blocked-uuids': ReadonlyArray<ServiceIdString>;
|
||||
|
|
|
@ -13,6 +13,7 @@ export const STORAGE_UI_KEYS: ReadonlyArray<keyof StorageAccessType> = [
|
|||
'audio-notification',
|
||||
'audioMessage',
|
||||
'auto-download-update',
|
||||
'autoConvertEmoji',
|
||||
'badge-count-muted-conversations',
|
||||
'call-ringtone-notification',
|
||||
'call-system-notification',
|
||||
|
|
|
@ -50,6 +50,7 @@ export type IPCEventsValuesType = {
|
|||
alwaysRelayCalls: boolean | undefined;
|
||||
audioNotification: boolean | undefined;
|
||||
audioMessage: boolean;
|
||||
autoConvertEmoji: boolean;
|
||||
autoDownloadUpdate: boolean;
|
||||
autoLaunch: boolean;
|
||||
callRingtoneNotification: boolean;
|
||||
|
@ -344,6 +345,8 @@ export function createIPCEvents(
|
|||
window.storage.get('auto-download-update', true),
|
||||
setAutoDownloadUpdate: value =>
|
||||
window.storage.put('auto-download-update', value),
|
||||
getAutoConvertEmoji: () => window.storage.get('autoConvertEmoji', false),
|
||||
setAutoConvertEmoji: value => window.storage.put('autoConvertEmoji', value),
|
||||
getSentMediaQualitySetting: () =>
|
||||
window.storage.get('sent-media-quality', 'standard'),
|
||||
setSentMediaQualitySetting: value =>
|
||||
|
|
|
@ -38,6 +38,7 @@ installCallback('syncRequest');
|
|||
installSetting('alwaysRelayCalls');
|
||||
installSetting('audioMessage');
|
||||
installSetting('audioNotification');
|
||||
installSetting('autoConvertEmoji');
|
||||
installSetting('autoDownloadUpdate');
|
||||
installSetting('autoLaunch');
|
||||
installSetting('callRingtoneNotification');
|
||||
|
|
|
@ -34,6 +34,7 @@ SettingsWindowProps.onRender(
|
|||
executeMenuRole,
|
||||
getConversationsWithCustomColor,
|
||||
hasAudioNotifications,
|
||||
hasAutoConvertEmoji,
|
||||
hasAutoDownloadUpdate,
|
||||
hasAutoLaunch,
|
||||
hasCallNotifications,
|
||||
|
@ -69,6 +70,7 @@ SettingsWindowProps.onRender(
|
|||
makeSyncRequest,
|
||||
notificationContent,
|
||||
onAudioNotificationsChange,
|
||||
onAutoConvertEmojiChange,
|
||||
onAutoDownloadUpdateChange,
|
||||
onAutoLaunchChange,
|
||||
onCallNotificationsChange,
|
||||
|
@ -135,6 +137,7 @@ SettingsWindowProps.onRender(
|
|||
executeMenuRole={executeMenuRole}
|
||||
getConversationsWithCustomColor={getConversationsWithCustomColor}
|
||||
hasAudioNotifications={hasAudioNotifications}
|
||||
hasAutoConvertEmoji={hasAutoConvertEmoji}
|
||||
hasAutoDownloadUpdate={hasAutoDownloadUpdate}
|
||||
hasAutoLaunch={hasAutoLaunch}
|
||||
hasCallNotifications={hasCallNotifications}
|
||||
|
@ -174,6 +177,7 @@ SettingsWindowProps.onRender(
|
|||
makeSyncRequest={makeSyncRequest}
|
||||
notificationContent={notificationContent}
|
||||
onAudioNotificationsChange={onAudioNotificationsChange}
|
||||
onAutoConvertEmojiChange={onAutoConvertEmojiChange}
|
||||
onAutoDownloadUpdateChange={onAutoDownloadUpdateChange}
|
||||
onAutoLaunchChange={onAutoLaunchChange}
|
||||
onCallNotificationsChange={onCallNotificationsChange}
|
||||
|
|
|
@ -22,6 +22,7 @@ function doneRendering() {
|
|||
|
||||
const settingMessageAudio = createSetting('audioMessage');
|
||||
const settingAudioNotification = createSetting('audioNotification');
|
||||
const settingAutoConvertEmoji = createSetting('autoConvertEmoji');
|
||||
const settingAutoDownloadUpdate = createSetting('autoDownloadUpdate');
|
||||
const settingAutoLaunch = createSetting('autoLaunch');
|
||||
const settingCallRingtoneNotification = createSetting(
|
||||
|
@ -140,6 +141,7 @@ async function renderPreferences() {
|
|||
blockedCount,
|
||||
deviceName,
|
||||
hasAudioNotifications,
|
||||
hasAutoConvertEmoji,
|
||||
hasAutoDownloadUpdate,
|
||||
hasAutoLaunch,
|
||||
hasCallNotifications,
|
||||
|
@ -181,6 +183,7 @@ async function renderPreferences() {
|
|||
blockedCount: settingBlockedCount.getValue(),
|
||||
deviceName: settingDeviceName.getValue(),
|
||||
hasAudioNotifications: settingAudioNotification.getValue(),
|
||||
hasAutoConvertEmoji: settingAutoConvertEmoji.getValue(),
|
||||
hasAutoDownloadUpdate: settingAutoDownloadUpdate.getValue(),
|
||||
hasAutoLaunch: settingAutoLaunch.getValue(),
|
||||
hasCallNotifications: settingCallSystemNotification.getValue(),
|
||||
|
@ -247,6 +250,7 @@ async function renderPreferences() {
|
|||
defaultConversationColor,
|
||||
deviceName,
|
||||
hasAudioNotifications,
|
||||
hasAutoConvertEmoji,
|
||||
hasAutoDownloadUpdate,
|
||||
hasAutoLaunch,
|
||||
hasCallNotifications,
|
||||
|
@ -320,6 +324,9 @@ async function renderPreferences() {
|
|||
onAudioNotificationsChange: attachRenderCallback(
|
||||
settingAudioNotification.setValue
|
||||
),
|
||||
onAutoConvertEmojiChange: attachRenderCallback(
|
||||
settingAutoConvertEmoji.setValue
|
||||
),
|
||||
onAutoDownloadUpdateChange: attachRenderCallback(
|
||||
settingAutoDownloadUpdate.setValue
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue