@@ -29,8 +29,9 @@ import QueryMatcher from './QueryMatcher';
2929import { PillCompletion } from './Components' ;
3030import { ICompletion , ISelectionRange } from './Autocompleter' ;
3131import SettingsStore from "../settings/SettingsStore" ;
32- import { EMOJI , IEmoji } from '../emoji' ;
32+ import { EMOJI , IEmoji , getEmojiFromUnicode } from '../emoji' ;
3333import { TimelineRenderingType } from '../contexts/RoomContext' ;
34+ import * as recent from '../emojipicker/recent' ;
3435
3536const LIMIT = 20 ;
3637
@@ -73,6 +74,7 @@ function colonsTrimmed(str: string): string {
7374export default class EmojiProvider extends AutocompleteProvider {
7475 matcher : QueryMatcher < ISortedEmoji > ;
7576 nameMatcher : QueryMatcher < ISortedEmoji > ;
77+ private readonly recentlyUsed : IEmoji [ ] ;
7678
7779 constructor ( room : Room , renderingType ?: TimelineRenderingType ) {
7880 super ( { commandRegex : EMOJI_REGEX , renderingType } ) ;
@@ -87,6 +89,8 @@ export default class EmojiProvider extends AutocompleteProvider {
8789 // For removing punctuation
8890 shouldMatchWordsOnly : true ,
8991 } ) ;
92+
93+ this . recentlyUsed = Array . from ( new Set ( recent . get ( ) . map ( getEmojiFromUnicode ) . filter ( Boolean ) ) ) ;
9094 }
9195
9296 async getCompletions (
@@ -109,7 +113,7 @@ export default class EmojiProvider extends AutocompleteProvider {
109113 // Do second match with shouldMatchWordsOnly in order to match against 'name'
110114 completions = completions . concat ( this . nameMatcher . match ( matchedString ) ) ;
111115
112- const sorters = [ ] ;
116+ let sorters = [ ] ;
113117 // make sure that emoticons come first
114118 sorters . push ( c => score ( matchedString , c . emoji . emoticon || "" ) ) ;
115119
@@ -130,6 +134,15 @@ export default class EmojiProvider extends AutocompleteProvider {
130134 sorters . push ( c => c . _orderBy ) ;
131135 completions = sortBy ( uniq ( completions ) , sorters ) ;
132136
137+ completions = completions . slice ( 0 , LIMIT ) ;
138+
139+ // Do a second sort to place emoji matching with frequently used one on top
140+ sorters = [ ] ;
141+ this . recentlyUsed . forEach ( emoji => {
142+ sorters . push ( c => score ( emoji . shortcodes [ 0 ] , c . emoji . shortcodes [ 0 ] ) ) ;
143+ } ) ;
144+ completions = sortBy ( uniq ( completions ) , sorters ) ;
145+
133146 completions = completions . map ( c => ( {
134147 completion : c . emoji . unicode ,
135148 component : (
@@ -138,7 +151,7 @@ export default class EmojiProvider extends AutocompleteProvider {
138151 </ PillCompletion >
139152 ) ,
140153 range,
141- } ) ) . slice ( 0 , LIMIT ) ;
154+ } ) ) ;
142155 }
143156 return completions ;
144157 }
0 commit comments