Skip to content

Commit 5c98d9b

Browse files
committed
Keep track of recently used symbols
bug: T110722 Change-Id: Ie2c3b63aabaec5b9955520a51c9c1b7501514423
1 parent d210240 commit 5c98d9b

File tree

5 files changed

+81
-2
lines changed

5 files changed

+81
-2
lines changed

i18n/en.json

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@
221221
"visualeditor-specialcharacter-group-set-accents": "{\"Æ\":\"Æ\",\"æ\":\"æ\",\"À\":\"À\",\"à\":\"à\",\"Â\":\"Â\",\"â\":\"â\",\"Ä\":\"Ä\",\"ä\":\"ä\",\"Å\":\"Å\",\"å\":\"å\",\"Ç\":\"Ç\",\"ç\":\"ç\",\"È\":\"È\",\"è\":\"è\",\"É\":\"É\",\"é\":\"é\",\"Ê\":\"Ê\",\"ê\":\"ê\",\"Ë\":\"Ë\",\"ë\":\"ë\",\"Î\":\"Î\",\"î\":\"î\",\"Ï\":\"Ï\",\"ï\":\"ï\",\"Ô\":\"Ô\",\"ô\":\"ô\",\"Ö\":\"Ö\",\"ö\":\"ö\",\"Ø\":\"Ø\",\"ø\":\"ø\",\"Ù\":\"Ù\",\"ù\":\"ù\",\"Û\":\"Û\",\"û\":\"û\",\"Ü\":\"Ü\",\"ü\":\"ü\",\"Ÿ\":\"Ÿ\",\"ÿ\":\"ÿ\",\"Œ\":\"Œ\",\"œ\":\"œ\"}",
222222
"visualeditor-specialcharacter-group-set-mathematical": "{\"\":\"\",\"×\":\"×\",\"÷\":\"÷\",\"\":\"\",\"\":\"\",\"\":\"\",\"\":\"\",\"±\":\"±\",\"¹\":\"¹\",\"²\":\"²\",\"³\":\"³\",\"\":\"\",\"\":\"\",\"\":\"\",\"\":\"\",\"\":\"\",\"\":\"\",\"\":\"\",\"½\":\"½\"}",
223223
"visualeditor-specialcharacter-group-set-symbols": "{\"\":\"\",\"\":\"\",\"°\":\"°\",\"\":\"\",\"\":\"\",\"\":\"\",\"\":\"\",\"« »\":\"« »\",\"“”\":\"“”\",\"#\":\"#\",\"@\":\"@\",\"|\":\"|\",\"~\":\"~\",\"§\":\"§\",\"\":\"\",\"·\":\"·\",\"\":\"\",\"\":\"\"}",
224+
"visualeditor-specialcharacter-recentlyused": "Recently used",
224225
"visualeditor-table-context-col": "Column",
225226
"visualeditor-table-context-row": "Row",
226227
"visualeditor-table-contextitem-properties": "Properties",

i18n/qqq.json

+1
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@
240240
"visualeditor-specialcharacter-group-set-accents": "This is a JSON string defining accent special characters that can be inserted using the special character insertion tool. It is not used in the MediaWiki version of VisualEditor.\n{{doc-important|Please make sure it is a valid JSON string.}}\n{{Optional}}",
241241
"visualeditor-specialcharacter-group-set-mathematical": "This is a JSON string defining mathematical special characters that can be inserted using the special character insertion tool. It is not used in the MediaWiki version of VisualEditor.\n{{doc-important|Please make sure it is a valid JSON string.}}\n{{Optional}}",
242242
"visualeditor-specialcharacter-group-set-symbols": "This is a JSON string defining symbol special characters that can be inserted using the special character insertion tool. It is not used in the MediaWiki version of VisualEditor.\n{{doc-important|Please make sure it is a valid JSON string.}}\n{{Optional}}",
243+
"visualeditor-specialcharacter-recentlyused": "Label to indicate the list of recently used characters in the symbol list table",
243244
"visualeditor-table-context-col": "Accessibility label for the menu of options for a table column.",
244245
"visualeditor-table-context-row": "Accessibility label for the menu of options for a table row.",
245246
"visualeditor-table-contextitem-properties": "Label for the properties button in the table context\n{{Identical|Property}}",

src/init/ve.init.Platform.js

+9
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ ve.init.Platform.prototype.getUserConfig = null;
158158
*/
159159
ve.init.Platform.prototype.setUserConfig = null;
160160

161+
/**
162+
* Determine whether we can store preferences
163+
*
164+
* @return {boolean}
165+
*/
166+
ve.init.Platform.prototype.canUseUserConfig = function () {
167+
return true;
168+
};
169+
161170
/**
162171
* Create a safe storage object
163172
*

src/ui/dialogs/ve.ui.SpecialCharacterDialog.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ ve.ui.SpecialCharacterDialog.prototype.initialize = function () {
5151
// Parent method
5252
ve.ui.SpecialCharacterDialog.super.prototype.initialize.call( this );
5353

54-
this.characterListLayout = new ve.ui.SymbolListBookletLayout();
54+
// Use 'visualeditor-symbolList-recentlyUsed-specialCharacters' in Hooks.php
55+
this.characterListLayout = new ve.ui.SymbolListBookletLayout( { preferenceNameSuffix: 'specialCharacters' } );
5556
this.characterListLayout.connect( this, {
5657
choose: 'onCharacterListChoose'
5758
} );
58-
// Character list is lazy-loaded the first time getSetupProcess runs
5959

6060
this.$body.append( this.characterListLayout.$element );
6161
};

src/ui/layouts/ve.ui.SymbolListBookletLayout.js

+68
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,28 @@ ve.ui.SymbolListBookletLayout = function VeUiSymbolListBookletLayout( config ) {
2222
continuous: true
2323
}, config ) );
2424

25+
if ( config.preferenceNameSuffix && ve.init.platform.canUseUserConfig() ) {
26+
this.recentlyUsedKey = 'visualeditor-symbolList-recentlyUsed-' + config.preferenceNameSuffix;
27+
this.recentlyUsed = ve.userConfig( this.recentlyUsedKey ) || [];
28+
}
29+
2530
this.$element.addClass( 've-ui-symbolListBookletLayout' );
2631
};
2732

2833
/* Inheritance */
2934

3035
OO.inheritClass( ve.ui.SymbolListBookletLayout, OO.ui.BookletLayout );
3136

37+
/* Static properties */
38+
39+
/**
40+
* Sets how many entries to keep in the "recently used" list
41+
*
42+
* @static
43+
* @property {number}
44+
*/
45+
ve.ui.SymbolListBookletLayout.static.maxRecentlyUsed = 32;
46+
3247
/* Methods */
3348

3449
/**
@@ -49,6 +64,58 @@ ve.ui.SymbolListBookletLayout.prototype.setSymbolData = function ( symbolData )
4964
'.ve-ui-symbolListPage-symbol',
5065
this.onListClick.bind( this )
5166
);
67+
68+
this.renderRecentlyUsed();
69+
};
70+
71+
/**
72+
* Set recent data
73+
*/
74+
ve.ui.SymbolListBookletLayout.prototype.renderRecentlyUsed = function () {
75+
if ( this.recentlyUsed === undefined ) {
76+
return;
77+
}
78+
const recentPage = new ve.ui.SymbolListPage( 'recent', {
79+
label: ve.msg( 'visualeditor-specialcharacter-recentlyused' ),
80+
symbols: this.recentlyUsed,
81+
attributes: { 'data-recent': '' }
82+
} );
83+
this.addPages( [ recentPage ], 0 );
84+
};
85+
86+
/**
87+
* Inserts a character at the start of the recently-used list and updates the user preference.
88+
*
89+
* @param {string|Object} character A symbol string or object
90+
* @param {boolean} fromRecentList Set when the symbol was chosen from the recently-used list. Inhibits a rerender.
91+
*/
92+
ve.ui.SymbolListBookletLayout.prototype.updateRecentlyUsed = function ( character, fromRecentList ) {
93+
if ( this.recentlyUsed === undefined ) {
94+
return;
95+
}
96+
97+
const seen = this.recentlyUsed.findIndex(
98+
( c ) => JSON.stringify( c ) === JSON.stringify( character )
99+
);
100+
if ( seen === 0 ) {
101+
// The character is already the most recently-used, so there's no need to update anything
102+
return;
103+
}
104+
if ( seen !== -1 ) {
105+
// This character is already in the list - remove it so we can re-insert it at the start
106+
this.recentlyUsed.splice( seen, 1 );
107+
}
108+
this.recentlyUsed.unshift( character );
109+
this.recentlyUsed = this.recentlyUsed.slice( 0, this.constructor.static.maxRecentlyUsed );
110+
111+
if ( this.recentlyUsedKey !== undefined ) {
112+
ve.userConfig( this.recentlyUsedKey, this.recentlyUsed );
113+
}
114+
115+
/* Avoid re-ordering the list under the user's cursor */
116+
if ( !fromRecentList ) {
117+
this.renderRecentlyUsed();
118+
}
52119
};
53120

54121
/**
@@ -61,5 +128,6 @@ ve.ui.SymbolListBookletLayout.prototype.onListClick = function ( e ) {
61128

62129
if ( symbol ) {
63130
this.emit( 'choose', symbol );
131+
this.updateRecentlyUsed( symbol, e.target.parentNode.hasAttribute( 'data-recent' ) );
64132
}
65133
};

0 commit comments

Comments
 (0)