Icon generator

This commit is contained in:
Eduard Kuzmenko 2022-04-09 20:24:12 +03:00
parent ea409d22c9
commit 19de0bb5d4
12 changed files with 3667 additions and 1133 deletions

View File

@ -15,6 +15,7 @@
"whybundled": "npm run profile && whybundled stats.json",
"generate-mtproto-types": "node ./src/scripts/generate_mtproto_types.js src/",
"generate-changelog": "node ./src/scripts/generate_changelog.js",
"generate-icons": "node ./src/scripts/icomoon/icomoon_generate.js",
"change-version": "node ./src/scripts/change_version.js"
},
"author": "",

View File

@ -13,7 +13,6 @@ import IS_EMOJI_SUPPORTED from './environment/emojiSupport';
import { IS_MOBILE_SAFARI } from './environment/userAgent';
import './materialize.scss';
import './scss/style.scss';
import './scss/tgico.scss';
/* import { computeCheck } from './lib/crypto/srp';
import { salt1, salt2, g, p, srp_id, secure_random, srp_B, password } from './mock/srp'; */

3
src/scripts/icomoon/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
node_modules
out
selection.json

View File

@ -0,0 +1,292 @@
// Thanks to https://github.com/Yuyz0112/icomoon-cli
const fs = require('fs-extra');
const path = require('path');
const extract = require('extract-zip');
const puppeteer = require('puppeteer');
const DEFAULT_TIMEOUT = 60000;
const PAGE = {
IMPORT_CONFIG_BUTTON: '.file.unit',
IMPORT_SELECTION_INPUT: '.file.unit input[type="file"]',
OVERLAY_CONFIRM: '.overlay button.mrl',
NEW_SET_BUTTON: '.menuList1 button',
MAIN_MENU_BUTTON: '.bar-top button .icon-menu',
MENU_BUTTON: 'h1 button .icon-menu',
MENU: '.menuList2.menuList3',
ICON_INPUT: '.menuList2.menuList3 .file input[type="file"]',
FIRST_ICON_BOX: '#set0 .miBox:not(.mi-selected)',
REMOVE_SET_BUTTON: '.menuList2.menuList3 li:last-child button',
SELECT_ALL_BUTTON: 'button[ng-click="selectAllNone($index, true)"]',
GENERATE_LINK: 'a[href="#/select/font"]',
GLYPH_SET: '#glyphSet0',
GLYPH_NAME: '.glyphName',
DOWNLOAD_BUTTON: '.btn4',
PREFERENCES: '#pref',
SHOW_METRICS: '[ng-class*="showMetricsFocused"] label',
CLOSE_OVERLAY: 'button[ng-click*="visiblePanels.fontPref = false"]',
IE8_SUPPORTED: '[ng-class*="noie8Focused"] .icon-checked',
IE8_DISABLE: 'label[ng-class*="noie8Focused"]',
FONT_NAME_INPUT: '[ng-model="fontPref.metadata.fontFamily"]',
CLASS_PREFIX_INPUT: '[ng-model="fontPref.prefix"]',
CSS_VARS_LABEL: '[ng-class*="fontPref.cssVars"]',
EM_HEIGHT_INPUT: '[model="fontPref.metrics.emSize"] input',
BASELINE_HEIGHT_INPUT: '[model="fontPref.metrics.baseline"] input',
WHITESPACE_WIDTH_INPUT: '[model="fontPref.metrics.whitespace"] input',
};
const DEFAULT_OPTIONS = {
outputDir: path.join(__dirname, 'output'),
};
const logger = (...args) => {
console.log('[icomoon-cli]', ...args);
};
const sleep = time => new Promise(resolve => setTimeout(resolve, time));
const getAbsolutePath = inputPath => {
let absoluteSelectionPath = inputPath;
if (!path.isAbsolute(inputPath)) {
if (!process.env.PWD) {
process.env.PWD = process.cwd();
}
absoluteSelectionPath = path.resolve(process.env.PWD, inputPath);
}
return absoluteSelectionPath;
};
const checkDownload = dest => new Promise((resolve, reject) => {
const interval = 1000;
let downloadSize = 0;
let timeCount = 0;
const timer = setInterval(async () => {
timeCount += interval;
/* const exist = await fs.exists(dest);
if (!exist) {
return;
} */
const stats = fs.statSync(dest);
if (stats.size > 0 && stats.size === downloadSize) {
clearInterval(timer);
resolve();
} else {
downloadSize = stats.size;
}
if (timeCount > DEFAULT_TIMEOUT) {
reject('Timeout when download file, please check your network.');
}
}, interval);
});
const checkDuplicateName = ({ selectionPath, icons, names }, forceOverride) => {
const iconNames = icons.map((icon, index) => {
if (names[index]) {
return names[index];
}
return path.basename(icon).replace(path.extname(icon), '');
});
const duplicates = [];
const selection = fs.readJSONSync(selectionPath);
selection.icons.forEach((icon, index) => {
const name = icon.tags[0];
if (iconNames.includes(name)) {
duplicates.push({ name, index });
}
});
if (!duplicates.length) {
return;
}
if (forceOverride) {
selection.icons = selection.icons.filter((icon, index) => !duplicates.some(d => d.index === index));
fs.writeJSONSync(selectionPath, selection, { spaces: 2 });
} else {
throw new Error(`Found duplicate icon names: ${duplicates.map(d => d.name).join(',')}`);
}
};
async function pipeline(options = {}) {
try {
const {
icons,
names = [],
selectionPath,
forceOverride = false,
whenFinished,
visible = false
} = options;
const outputDir = options.outputDir ? getAbsolutePath(options.outputDir) : DEFAULT_OPTIONS.outputDir;
// prepare stage
logger('Preparing...');
if(!icons || !icons.length) {
if(whenFinished) {
whenFinished({ outputDir });
}
return logger('No new icons found.');
}
if(!selectionPath) {
throw new Error('Please config a valid selection file path.');
}
let absoluteSelectionPath = getAbsolutePath(selectionPath);
// checkDuplicateName({
// selectionPath: absoluteSelectionPath,
// icons,
// names,
// }, forceOverride);
await fs.remove(outputDir);
await fs.ensureDir(outputDir);
const browser = await puppeteer.launch({headless: !visible});
logger('Started a new chrome instance, going to load icomoon.io.');
const page = await (await browser).newPage();
await page._client.send('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: outputDir
});
await page.goto('https://icomoon.io/app/#/select');
await page.waitForSelector(PAGE.IMPORT_CONFIG_BUTTON);
logger('Dashboard is visible, going to upload config file');
// remove init set
await page.click(PAGE.MENU_BUTTON);
await page.click(PAGE.REMOVE_SET_BUTTON);
const importInput = await page.waitForSelector(PAGE.IMPORT_SELECTION_INPUT);
await importInput.uploadFile(absoluteSelectionPath);
logger('Uploaded config, going to upload new icon files');
try {
await Promise.race([
sleep(1000).then(() => {
throw 0;
}),
page.waitForSelector(PAGE.OVERLAY_CONFIRM, { visible: true })
]);
await page.click(PAGE.OVERLAY_CONFIRM);
} catch(err) {
logger('Overlay is missed?');
}
const selection = fs.readJSONSync(selectionPath);
/* if (selection.icons.length === 0) {
logger('Selection icons is empty, going to create an empty set');
await page.click(PAGE.MAIN_MENU_BUTTON);
await page.waitForSelector(PAGE.NEW_SET_BUTTON, { visible: true });
await page.click(PAGE.NEW_SET_BUTTON);
} */
await page.click(PAGE.MENU_BUTTON);
const iconInput = await page.waitForSelector(PAGE.ICON_INPUT);
const iconPaths = icons.map(getAbsolutePath);
await iconInput.uploadFile(...iconPaths);
await page.waitForSelector(PAGE.FIRST_ICON_BOX);
await page.click(PAGE.SELECT_ALL_BUTTON);
logger('Uploaded and selected all new icons');
await page.click(PAGE.GENERATE_LINK);
await page.waitForSelector(PAGE.GLYPH_SET);
await page.click(PAGE.PREFERENCES);
try {
await Promise.race([
sleep(1000).then(() => {
throw 0;
}),
page.waitForSelector(PAGE.IE8_SUPPORTED)
]);
await page.click(PAGE.IE8_DISABLE);
} catch(err) {
logger('IE8 is already disabled');
}
async function fillInput(selector, value) {
if(typeof(value) !== 'string') {
value = '' + value;
}
await page.focus(selector);
for(let i = 0; i < 100; ++i) {
await page.keyboard.press('Backspace');
}
await page.keyboard.type(value);
}
await fillInput(PAGE.FONT_NAME_INPUT, selection.preferences.fontPref.metadata.fontFamily);
await fillInput(PAGE.CLASS_PREFIX_INPUT, selection.preferences.fontPref.prefix);
await page.click(PAGE.CSS_VARS_LABEL);
await page.click(PAGE.SHOW_METRICS);
await fillInput(PAGE.EM_HEIGHT_INPUT, selection.preferences.fontPref.metrics.emSize);
await fillInput(PAGE.BASELINE_HEIGHT_INPUT, selection.preferences.fontPref.metrics.baseline);
await fillInput(PAGE.WHITESPACE_WIDTH_INPUT, selection.preferences.fontPref.metrics.whitespace);
// await sleep(100000);
await page.click(PAGE.CLOSE_OVERLAY);
// (await page.waitForSelector(PAGE.FONT_NAME_INPUT)).;
// if(names.length) {
// logger('Changed names of icons');
// // sleep to ensure indexedDB is ready
// await sleep(1000);
// await page.evaluate(names => {
// const request = indexedDB.open('IDBWrapper-storage', 1);
// request.onsuccess = function() {
// const db = request.result;
// const tx = db.transaction('storage', 'readwrite');
// const store = tx.objectStore('storage');
// const keys = store.getAllKeys();
// keys.onsuccess = function() {
// let timestamp;
// keys.result.forEach(function(key) {
// if (typeof key === 'number') {
// timestamp = key;
// }
// });
// const main = store.get(timestamp);
// main.onsuccess = function() {
// const data = main.result;
// for (let i = 0; i < names.length; i++) {
// data.obj.iconSets[0].selection[i].name = names[i];
// }
// store.put(data);
// };
// };
// };
// }, names);
// }
// // sleep to ensure the code was executed
// await sleep(1000);
// // reload the page let icomoon read latest indexedDB data
// await page.reload();
await sleep(2000);
await page.waitForSelector(PAGE.DOWNLOAD_BUTTON);
await page.click(PAGE.DOWNLOAD_BUTTON);
const meta = selection.preferences.fontPref.metadata;
const zipName = meta.majorVersion
? `${meta.fontFamily}-v${meta.majorVersion}.${meta.minorVersion || 0}.zip`
: `${meta.fontFamily}.zip`;
logger(`Started to download ${zipName}`);
const zipPath = path.join(outputDir, zipName);
await checkDownload(zipPath);
logger('Successfully downloaded, going to unzip it.');
await page.close();
await browser.close();
// unzip stage
extract(zipPath, {dir: outputDir}, async(err) => {
if(err) {
throw err;
}
await fs.remove(zipPath);
logger(`Finished. The output directory is ${outputDir}.`);
if(whenFinished) {
whenFinished({outputDir});
}
});
} catch(error) {
console.error(error);
}
}
module.exports = pipeline;

View File

@ -0,0 +1,52 @@
// @ts-check
const pipeline = require('./icomoon');
const fs = require('fs');
const path = require('path');
const iconsPath = path.join(__dirname, '../../../tweb-design/JS_3/Icons/');
const files = fs.readdirSync(iconsPath);
const icons = files.filter(file => file.endsWith('.svg')).map(file => iconsPath + file);
function moveFiles(outPath) {
// const path = './out/';
const stylesOutPath = path.join(__dirname, '../../scss/tgico/_');
let styleText = fs.readFileSync(outPath + 'style.scss').toString();
styleText = styleText
.replace(/icomoon/g, 'tgico')
.replace('[class^="tgico-"], [class*=" tgico-"]', `/* [class^="tgico-"]:before,
[class^="tgico-"]:after, */
[class^="tgico-"],
.tgico:before,
.tgico:after,
[class*=" tgico-"]:before,
[class*=" tgico-"]:after`);
fs.writeFileSync(stylesOutPath + 'style.scss', styleText);
let variablesText = fs.readFileSync(outPath + 'variables.scss').toString();
variablesText = variablesText.slice(variablesText.indexOf('\n\n') + 2);
fs.writeFileSync(stylesOutPath + 'variables.scss', variablesText);
const fontsPath = outPath + 'fonts/';
const files = fs.readdirSync(fontsPath);
files.forEach(fileName => {
fs.cpSync(fontsPath + fileName, path.join(__dirname, '../../../public/assets/fonts/' + fileName));
});
}
// moveFiles();
// process.exit(0);
pipeline({
icons,
// names: ['new1', 'new2'],
selectionPath: path.join(__dirname, './selection.json'),
outputDir: path.join(__dirname, './out'),
forceOverride: true,
visible: false,
whenFinished: (result) => {
moveFiles(result.outputDir + '/');
}
});

2162
src/scripts/icomoon/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
{
"name": "icomoon",
"version": "1.0.0",
"description": "",
"main": "icomoon_generate.js",
"scripts": {
"start": "node icomoon_generate.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"extract-zip": "^1.6.6",
"fs-extra": "^4.0.2",
"puppeteer": "^13.5.2",
"yargs": "^10.0.3"
}
}

View File

@ -1,198 +0,0 @@
/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
// ! https://icomoon.io/app/#/select
$tgico-font-family: "tgico" !default;
$tgico-font-path: "assets/fonts" !default;
/*
! CAN RUN IN DEVELOPER TOOLS TO CONVERT FONT TO VARIABLES:
`.tgico-select:before {
content: "\e900";
}`
.toLowerCase()
.replace(/([\s])|(_svg)|(1x)/g, '')
.replace(/\.(.+?):before\{content:"(.+?);\}/g, `$$$1: "\\$2;\n`);
*/
$tgico-check: "\e900";
$tgico-checks: "\e901";
$tgico-activesessions: "\e902";
$tgico-add_reaction: "\e903";
$tgico-add: "\e904";
$tgico-addmember_filled: "\e905";
$tgico-adduser: "\e906";
$tgico-admin: "\e907";
$tgico-animals: "\e908";
$tgico-animations: "\e909";
$tgico-archive: "\e90a";
$tgico-arrow_down: "\e90b";
$tgico-arrow_next: "\e90c";
$tgico-attach: "\e90d";
$tgico-avatarnext: "\e90e";
$tgico-avatarprevious: "\e90f";
$tgico-bold: "\e910";
$tgico-botcom: "\e911";
$tgico-bots: "\e912";
$tgico-bug: "\e913";
$tgico-calendar: "\e914";
$tgico-calendarfilter: "\e915";
$tgico-camera: "\e916";
$tgico-cameraadd: "\e917";
$tgico-car: "\e918";
$tgico-channel: "\e919";
$tgico-channelviews: "\e91a";
$tgico-chatspinned: "\e91b";
$tgico-chatsplaceholder: "\e91c";
$tgico-check1: "\e91d";
$tgico-checkbox: "\e91e";
$tgico-checkboxblock: "\e91f";
$tgico-checkboxempty: "\e920";
$tgico-checkboxon: "\e921";
$tgico-checkretract: "\e922";
$tgico-checkround: "\e923";
$tgico-close: "\e924";
$tgico-clouddownload: "\e925";
$tgico-colorize: "\e926";
$tgico-comments: "\e927";
$tgico-commentssticker: "\e928";
$tgico-copy: "\e929";
$tgico-darkmode: "\e92a";
$tgico-data: "\e92b";
$tgico-delete_filled: "\e92c";
$tgico-delete: "\e92d";
$tgico-deletedaccount: "\e92e";
$tgico-deleteleft: "\e92f";
$tgico-deleteuser: "\e930";
$tgico-devices: "\e931";
$tgico-document: "\e932";
$tgico-down: "\e933";
$tgico-download: "\e934";
$tgico-dragfiles: "\e935";
$tgico-dragmedia: "\e936";
$tgico-eats: "\e937";
$tgico-edit: "\e938";
$tgico-email: "\e939";
$tgico-endcall_filled: "\e93a";
$tgico-enter: "\e93b";
$tgico-eye1: "\e93c";
$tgico-eye2: "\e93d";
$tgico-fast_forward: "\e93e";
$tgico-fast_rewind: "\e93f";
$tgico-favourites: "\e940";
$tgico-flag: "\e941";
$tgico-folder: "\e942";
$tgico-fontsize: "\e943";
$tgico-forward_filled: "\e944";
$tgico-forward: "\e945";
$tgico-fullscreen: "\e946";
$tgico-gc_microphone: "\e947";
$tgico-gc_microphoneoff: "\e948";
$tgico-gifs: "\e949";
$tgico-group: "\e94a";
$tgico-help: "\e94b";
$tgico-image: "\e94c";
$tgico-info: "\e94d";
$tgico-info2: "\e94e";
$tgico-italic: "\e94f";
$tgico-keyboard: "\e950";
$tgico-lamp: "\e951";
$tgico-language: "\e952";
$tgico-largepause: "\e953";
$tgico-largeplay: "\e954";
$tgico-left: "\e955";
$tgico-link: "\e956";
$tgico-listscreenshare: "\e957";
$tgico-livelocation: "\e958";
$tgico-location: "\e959";
$tgico-lock: "\e95a";
$tgico-lockoff: "\e95b";
$tgico-loginlogodesktop: "\e95c";
$tgico-loginlogomobile: "\e95d";
$tgico-logout: "\e95e";
$tgico-mention: "\e95f";
$tgico-menu: "\e960";
$tgico-message: "\e961";
$tgico-messageunread: "\e962";
$tgico-microphone: "\e963";
$tgico-minus: "\e964";
$tgico-monospace: "\e965";
$tgico-more: "\e966";
$tgico-mute: "\e967";
$tgico-muted: "\e968";
$tgico-newchannel: "\e969";
$tgico-newchat_filled: "\e96a";
$tgico-newgroup: "\e96b";
$tgico-newprivate: "\e96c";
$tgico-next: "\e96d";
$tgico-noncontacts: "\e96e";
$tgico-nosound: "\e96f";
$tgico-passwordoff: "\e970";
$tgico-pause: "\e971";
$tgico-permissions: "\e972";
$tgico-phone: "\e973";
$tgico-pin: "\e974";
$tgico-pinlist: "\e975";
$tgico-pinned_filled: "\e976";
$tgico-pinnedchat: "\e977";
$tgico-play: "\e978";
$tgico-playback_1x: "\e979";
$tgico-playback_2x: "\e97a";
$tgico-playback_05: "\e97b";
$tgico-playback_15: "\e97c";
$tgico-plus: "\e97d";
$tgico-poll: "\e97e";
$tgico-previous: "\e97f";
$tgico-radiooff: "\e980";
$tgico-radioon: "\e981";
$tgico-reactions: "\e982";
$tgico-readchats: "\e983";
$tgico-recent: "\e984";
$tgico-replace: "\e985";
$tgico-reply_filled: "\e986";
$tgico-reply: "\e987";
$tgico-rightpanel: "\e988";
$tgico-saved: "\e989";
$tgico-savedmessages: "\e98a";
$tgico-schedule: "\e98b";
$tgico-scheduled: "\e98c";
$tgico-search: "\e98d";
$tgico-select: "\e98e";
$tgico-send: "\e98f";
$tgico-send2: "\e990";
$tgico-sending: "\e991";
$tgico-sendingerror: "\e992";
$tgico-settings_filled: "\e993";
$tgico-settings: "\e994";
$tgico-sharescreen_filled: "\e995";
$tgico-smallscreen: "\e996";
$tgico-smile: "\e997";
$tgico-spoiler: "\e998";
$tgico-sport: "\e999";
$tgico-stickers: "\e99a";
$tgico-stop: "\e99b";
$tgico-strikethrough: "\e99c";
$tgico-textedit: "\e99d";
$tgico-tip: "\e99e";
$tgico-tools: "\e99f";
$tgico-unarchive: "\e9a0";
$tgico-underline: "\e9a1";
$tgico-unmute: "\e9a2";
$tgico-unpin: "\e9a3";
$tgico-unread: "\e9a4";
$tgico-up: "\e9a5";
$tgico-user: "\e9a6";
$tgico-username: "\e9a7";
$tgico-videocamera_filled: "\e9a8";
$tgico-videocamera: "\e9a9";
$tgico-videochat: "\e9aa";
$tgico-volume_down: "\e9ab";
$tgico-volume_mute: "\e9ac";
$tgico-volume_off: "\e9ad";
$tgico-volume_up: "\e9ae";
$tgico-zoomin: "\e9af";
$tgico-zoomout: "\e9b0";

View File

@ -289,7 +289,7 @@ $chat-input-inner-padding-handhelds: .25rem;
// * Night theme end
}
@import "partials/ico";
@import "tgico";
@import "partials/input";
@import "partials/button";
@import "partials/animatedIcon";

View File

@ -4,5 +4,20 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
@import "partials/ico";
@import "partials/fonts";
// ! https://icomoon.io/app/#/select
$tgico-font-family: "tgico" !default;
$tgico-font-path: "assets/fonts" !default;
/*
! CAN RUN IN DEVELOPER TOOLS TO CONVERT FONT TO VARIABLES:
`.tgico-select:before {
content: "\e900";
}`
.toLowerCase()
.replace(/([\s])|(_svg)|(1x)/g, '')
.replace(/\.(.+?):before\{content:"(.+?);\}/g, `$$$1: "\\$2;\n`);
*/
@import "tgico/style";
@import "tgico/variables";

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,182 @@
$tgico-check: "\e900";
$tgico-checks: "\e901";
$tgico-activesessions: "\e902";
$tgico-add: "\e903";
$tgico-add_reaction: "\e904";
$tgico-addmember_filled: "\e905";
$tgico-adduser: "\e906";
$tgico-admin: "\e907";
$tgico-animals: "\e908";
$tgico-animations: "\e909";
$tgico-archive: "\e90a";
$tgico-arrow_down: "\e90b";
$tgico-arrow_next: "\e90c";
$tgico-attach: "\e90d";
$tgico-audio_repeat: "\e90e";
$tgico-audio_repeat_single: "\e90f";
$tgico-avatarnext: "\e910";
$tgico-avatarprevious: "\e911";
$tgico-bold: "\e912";
$tgico-botcom: "\e913";
$tgico-bots: "\e914";
$tgico-bug: "\e915";
$tgico-calendar: "\e916";
$tgico-calendarfilter: "\e917";
$tgico-camera: "\e918";
$tgico-cameraadd: "\e919";
$tgico-car: "\e91a";
$tgico-channel: "\e91b";
$tgico-channelviews: "\e91c";
$tgico-chatspinned: "\e91d";
$tgico-chatsplaceholder: "\e91e";
$tgico-check1: "\e91f";
$tgico-checkbox: "\e920";
$tgico-checkboxblock: "\e921";
$tgico-checkboxempty: "\e922";
$tgico-checkboxon: "\e923";
$tgico-checkretract: "\e924";
$tgico-checkround: "\e925";
$tgico-close: "\e926";
$tgico-clouddownload: "\e927";
$tgico-colorize: "\e928";
$tgico-comments: "\e929";
$tgico-commentssticker: "\e92a";
$tgico-copy: "\e92b";
$tgico-darkmode: "\e92c";
$tgico-data: "\e92d";
$tgico-delete: "\e92e";
$tgico-delete_filled: "\e92f";
$tgico-deletedaccount: "\e930";
$tgico-deleteleft: "\e931";
$tgico-deleteuser: "\e932";
$tgico-devices: "\e933";
$tgico-document: "\e934";
$tgico-down: "\e935";
$tgico-download: "\e936";
$tgico-dragfiles: "\e937";
$tgico-dragmedia: "\e938";
$tgico-eats: "\e939";
$tgico-edit: "\e93a";
$tgico-email: "\e93b";
$tgico-endcall: "\e93c";
$tgico-endcall_filled: "\e93d";
$tgico-enter: "\e93e";
$tgico-eye1: "\e93f";
$tgico-eye2: "\e940";
$tgico-fast_forward: "\e941";
$tgico-fast_rewind: "\e942";
$tgico-favourites: "\e943";
$tgico-flag: "\e944";
$tgico-folder: "\e945";
$tgico-fontsize: "\e946";
$tgico-forward: "\e947";
$tgico-forward_filled: "\e948";
$tgico-fullscreen: "\e949";
$tgico-gc_microphone: "\e94a";
$tgico-gc_microphoneoff: "\e94b";
$tgico-gifs: "\e94c";
$tgico-group: "\e94d";
$tgico-help: "\e94e";
$tgico-image: "\e94f";
$tgico-info: "\e950";
$tgico-info2: "\e951";
$tgico-italic: "\e952";
$tgico-keyboard: "\e953";
$tgico-lamp: "\e954";
$tgico-language: "\e955";
$tgico-largepause: "\e956";
$tgico-largeplay: "\e957";
$tgico-left: "\e958";
$tgico-link: "\e959";
$tgico-listscreenshare: "\e95a";
$tgico-livelocation: "\e95b";
$tgico-location: "\e95c";
$tgico-lock: "\e95d";
$tgico-lockoff: "\e95e";
$tgico-loginlogodesktop: "\e95f";
$tgico-loginlogomobile: "\e960";
$tgico-logout: "\e961";
$tgico-mention: "\e962";
$tgico-menu: "\e963";
$tgico-message: "\e964";
$tgico-messageunread: "\e965";
$tgico-microphone: "\e966";
$tgico-minus: "\e967";
$tgico-monospace: "\e968";
$tgico-more: "\e969";
$tgico-mute: "\e96a";
$tgico-muted: "\e96b";
$tgico-newchannel: "\e96c";
$tgico-newchat_filled: "\e96d";
$tgico-newgroup: "\e96e";
$tgico-newprivate: "\e96f";
$tgico-next: "\e970";
$tgico-noncontacts: "\e971";
$tgico-nosound: "\e972";
$tgico-passwordoff: "\e973";
$tgico-pause: "\e974";
$tgico-permissions: "\e975";
$tgico-phone: "\e976";
$tgico-pin: "\e977";
$tgico-pinlist: "\e978";
$tgico-pinned_filled: "\e979";
$tgico-pinnedchat: "\e97a";
$tgico-pip: "\e97b";
$tgico-play: "\e97c";
$tgico-playback_05: "\e97d";
$tgico-playback_15: "\e97e";
$tgico-playback_1x: "\e97f";
$tgico-playback_2x: "\e980";
$tgico-plus: "\e981";
$tgico-poll: "\e982";
$tgico-previous: "\e983";
$tgico-radiooff: "\e984";
$tgico-radioon: "\e985";
$tgico-reactions: "\e986";
$tgico-readchats: "\e987";
$tgico-recent: "\e988";
$tgico-replace: "\e989";
$tgico-reply: "\e98a";
$tgico-reply_filled: "\e98b";
$tgico-rightpanel: "\e98c";
$tgico-saved: "\e98d";
$tgico-savedmessages: "\e98e";
$tgico-schedule: "\e98f";
$tgico-scheduled: "\e990";
$tgico-search: "\e991";
$tgico-select: "\e992";
$tgico-send: "\e993";
$tgico-send2: "\e994";
$tgico-sending: "\e995";
$tgico-sendingerror: "\e996";
$tgico-settings: "\e997";
$tgico-settings_filled: "\e998";
$tgico-sharescreen_filled: "\e999";
$tgico-smallscreen: "\e99a";
$tgico-smile: "\e99b";
$tgico-spoiler: "\e99c";
$tgico-sport: "\e99d";
$tgico-stickers: "\e99e";
$tgico-stop: "\e99f";
$tgico-strikethrough: "\e9a0";
$tgico-textedit: "\e9a1";
$tgico-tip: "\e9a2";
$tgico-tools: "\e9a3";
$tgico-unarchive: "\e9a4";
$tgico-underline: "\e9a5";
$tgico-unmute: "\e9a6";
$tgico-unpin: "\e9a7";
$tgico-unread: "\e9a8";
$tgico-up: "\e9a9";
$tgico-user: "\e9aa";
$tgico-username: "\e9ab";
$tgico-videocamera: "\e9ac";
$tgico-videocamera_filled: "\e9ad";
$tgico-videochat: "\e9ae";
$tgico-volume_down: "\e9af";
$tgico-volume_mute: "\e9b0";
$tgico-volume_off: "\e9b1";
$tgico-volume_up: "\e9b2";
$tgico-zoomin: "\e9b3";
$tgico-zoomout: "\e9b4";