Skip to content

Commit b109f21

Browse files
committedJan 9, 2025··
Allow sending suggestions without FS API
1 parent faa2734 commit b109f21

File tree

1 file changed

+134
-57
lines changed

1 file changed

+134
-57
lines changed
 

‎editor.html

+134-57
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@
123123
padding: 10px;
124124
}
125125

126+
button.for-icon {
127+
padding: 10px;
128+
}
129+
126130
button>.icon {
127131
margin-right: 5px;
128132
font-size: 1.4rem;
@@ -487,6 +491,10 @@
487491
max-height: 100px;
488492
font-family: Arial, sans-serif;
489493
}
494+
495+
button .icon:last-child {
496+
margin: 0;
497+
}
490498
</style>
491499
<style id="dynamicStyles"></style>
492500
<title>Limits Editor</title>
@@ -495,6 +503,18 @@
495503
<body>
496504
<div class="start-screen" id="start-screen">
497505
<h1>Telegram Limits Editor</h1>
506+
<article>
507+
<p>
508+
Click the button below to suggest an edit to the @tginfo team.
509+
</p>
510+
<p>
511+
<b>Note</b>: We do not accept translations through this form. Please go to <a
512+
href="https://crowdin.com/project/telegram-limits" target="_blank">Crowdin</a> for translation.
513+
</p>
514+
</article>
515+
<p>
516+
<button onclick="EditorUi.startSubmission()" id="suggestButton">Suggest an Edit</button>
517+
</p>
498518
<article>
499519
<p>Edit limits in your cloned Telegram-Limits folder. When you click Save – files are updated right on your
500520
disk. No downloads required.</p>
@@ -509,7 +529,7 @@ <h1>Telegram Limits Editor</h1>
509529
<p><code>git clone git@github.com:tginfo/Telegram-Limits.git</code></p>
510530
</article>
511531
<p>
512-
<button onclick="EditorUi.newSession()">Pick <code>Telegram-Limits</code> Folder</button>
532+
<button onclick="EditorUi.newSession()" class="secondary">Pick <code>Telegram-Limits</code> Folder</button>
513533

514534
<button onclick="EditorUi.downloadFiles()" id="downloadNewButton" class="secondary">
515535
Open a Folder & Download Files
@@ -601,6 +621,15 @@ <h1>Telegram Limits Editor</h1>
601621
return handle;
602622
}
603623

624+
static parseIconCodePoints(iconCodePointsText) {
625+
return iconCodePointsText.split('\n').reduce((acc, line) => {
626+
const [name, codePoint] = line.split(' ');
627+
acc[name] = codePoint;
628+
629+
return acc;
630+
}, {});
631+
}
632+
604633
async readFiles() {
605634
const structureHandle = await this.handle.getDirectoryHandle('data');
606635
const structureFile = await structureHandle.getFileHandle('structure.json');
@@ -628,12 +657,7 @@ <h1>Telegram Limits Editor</h1>
628657
const iconObjectUrl = URL.createObjectURL(icon);
629658
const iconCodePointsText = await iconCodePoints.text();
630659

631-
const iconCodePointsMap = iconCodePointsText.split('\n').reduce((acc, line) => {
632-
const [name, codePoint] = line.split(' ');
633-
acc[name] = codePoint;
634-
635-
return acc;
636-
}, {});
660+
const iconCodePointsMap = WorkDirHandle.parseIconCodePoints(iconCodePointsText);
637661

638662
this.structureFile = structureFile;
639663
this.localizationFile = localizationFile;
@@ -830,6 +854,7 @@ <h1>Telegram Limits Editor</h1>
830854
static isDirty = false;
831855
static contentElement = null;
832856
static draggingType = null;
857+
static noFsMode = false;
833858

834859
static async openHelp(source) {
835860
alert("We're already working on documentation. Until then, for guidance, please contact contributors directly.");
@@ -844,7 +869,10 @@ <h1>Telegram Limits Editor</h1>
844869
<p>
845870
<b>Note:</b> We do not accept translations through this form.
846871
Please go to <a href="https://crowdin.com/project/telegram-limits" target="_blank">Crowdin</a> for translation.
847-
</p>
872+
</p>
873+
<p>
874+
Please group your changes into a single suggestion. Don't submit more often than once-twice a day.
875+
</p>
848876
</article>
849877
<label>
850878
<span>Description:</span>
@@ -905,12 +933,6 @@ <h1>Telegram Limits Editor</h1>
905933
}
906934

907935
static async check() {
908-
if (!('showDirectoryPicker' in window)) {
909-
alert('Your browser does not support the File System Access API. ' +
910-
'Please use a Chromium-based browser, like Google Chrome. Only Desktop version is supported.');
911-
return;
912-
}
913-
914936
const handle = await WorkDirHandle.checkHandleInIdb();
915937

916938
if (handle) {
@@ -949,6 +971,12 @@ <h1>Telegram Limits Editor</h1>
949971
}
950972

951973
static async newSession() {
974+
if (!('showDirectoryPicker' in window)) {
975+
alert('Your browser does not support the File System Access API. ' +
976+
'Please use a Chromium-based browser, like Google Chrome. Only Desktop version is supported.');
977+
return;
978+
}
979+
952980
try {
953981
this.workDirHandle = new WorkDirHandle(await WorkDirHandle.createNewHandle());
954982
const data = await this.workDirHandle.readFiles();
@@ -969,9 +997,61 @@ <h1>Telegram Limits Editor</h1>
969997
}
970998
}
971999

1000+
static async startSubmission() {
1001+
const button = document.getElementById('suggestButton');
1002+
button.disabled = true;
1003+
button.textContent = 'Downloading...';
1004+
1005+
try {
1006+
const { structureBlob, localizationBlob, iconBlob, iconCodePointsBlob } = await this.downloadBlobs('master');
1007+
1008+
const structureText = await structureBlob.text();
1009+
const localizationText = await localizationBlob.text();
1010+
const iconCodePointsText = await iconCodePointsBlob.text();
9721011

1012+
const structure = JSON.parse(structureText);
1013+
const localization = JSON.parse(localizationText);
1014+
const iconObjectUrl = URL.createObjectURL(iconBlob);
1015+
const iconCodePointsMap = WorkDirHandle.parseIconCodePoints(iconCodePointsText);
1016+
1017+
this.noFsMode = true;
1018+
this.applyData({ structure, localization, iconCodePointsMap, iconObjectUrl });
1019+
} catch (e) {
1020+
console.error(e);
1021+
alert('An error occurred while starting: ' + e.message);
1022+
} finally {
1023+
button.disabled = false;
1024+
button.textContent = 'Suggest an Edit';
1025+
}
1026+
}
1027+
1028+
static async downloadBlobs(branchName) {
1029+
const urlPrefix = 'https://raw.githubusercontent.com/tginfo/Telegram-Limits/' + branchName;
1030+
const structureUrl = `${urlPrefix}/data/structure.json`;
1031+
const localizationUrl = `${urlPrefix}/localization/en/data.json`;
1032+
const iconUrl = `${urlPrefix}/assets/images/icons.woff2`;
1033+
const iconCodePointsUrl = `${urlPrefix}/assets/images/icons.codepoints`;
1034+
1035+
const structureResponse = await fetch(structureUrl);
1036+
const localizationResponse = await fetch(localizationUrl);
1037+
const iconResponse = await fetch(iconUrl);
1038+
const iconCodePointsResponse = await fetch(iconCodePointsUrl);
1039+
1040+
const structureBlob = await structureResponse.blob();
1041+
const localizationBlob = await localizationResponse.blob();
1042+
const iconBlob = await iconResponse.blob();
1043+
const iconCodePointsBlob = await iconCodePointsResponse.blob();
1044+
1045+
return { structureBlob, localizationBlob, iconBlob, iconCodePointsBlob };
1046+
}
9731047

9741048
static async downloadFiles() {
1049+
if (!('showDirectoryPicker' in window)) {
1050+
alert('Your browser does not support the File System Access API. ' +
1051+
'Please use a Chromium-based browser, like Google Chrome. Only Desktop version is supported.');
1052+
return;
1053+
}
1054+
9751055
const button = document.getElementById('downloadNewButton');
9761056
try {
9771057
button.disabled = true;
@@ -1001,22 +1081,7 @@ <h1>Telegram Limits Editor</h1>
10011081
const iconFile = await iconImagesHandle.getFileHandle('icons.woff2', { create: true });
10021082
const iconCodePointsFile = await iconImagesHandle.getFileHandle('icons.codepoints', { create: true });
10031083

1004-
1005-
const urlPrefix = 'https://raw.githubusercontent.com/tginfo/Telegram-Limits/' + branchName;
1006-
const structureUrl = `${urlPrefix}/data/structure.json`;
1007-
const localizationUrl = `${urlPrefix}/localization/en/data.json`;
1008-
const iconUrl = `${urlPrefix}/assets/images/icons.woff2`;
1009-
const iconCodePointsUrl = `${urlPrefix}/assets/images/icons.codepoints`;
1010-
1011-
const structureResponse = await fetch(structureUrl);
1012-
const localizationResponse = await fetch(localizationUrl);
1013-
const iconResponse = await fetch(iconUrl);
1014-
const iconCodePointsResponse = await fetch(iconCodePointsUrl);
1015-
1016-
const structureBlob = await structureResponse.blob();
1017-
const localizationBlob = await localizationResponse.blob();
1018-
const iconBlob = await iconResponse.blob();
1019-
const iconCodePointsBlob = await iconCodePointsResponse.blob();
1084+
const { structureBlob, localizationBlob, iconBlob, iconCodePointsBlob } = await this.downloadBlobs(branchName);
10201085

10211086
const structureWritable = await structureFile.createWritable();
10221087
await structureWritable.write(structureBlob);
@@ -1102,39 +1167,51 @@ <h1>Telegram Limits Editor</h1>
11021167
toolbar.appendChild(helpButton);
11031168

11041169
const sendButton = document.createElement('button');
1105-
sendButton.classList.add('icon');
1106-
sendButton.classList.add('secondary');
1107-
sendButton.textContent = 'send';
1170+
if (!this.noFsMode) sendButton.classList.add('for-icon');
1171+
if (!this.noFsMode) sendButton.classList.add('secondary');
11081172
sendButton.title = 'Send The Edit to @tginfo';
11091173
sendButton.addEventListener('click', () => EditorUi.suggestEdit());
11101174
toolbar.appendChild(sendButton);
11111175

1112-
const saveButton = document.createElement('button');
1113-
saveButton.classList.add('icon');
1114-
saveButton.classList.add('secondary');
1115-
saveButton.textContent = 'save';
1116-
saveButton.title = 'Save to Disk';
1117-
saveButton.addEventListener('click', () => this.save());
1118-
toolbar.appendChild(saveButton);
1119-
1120-
const saveStatus = document.createElement('span');
1121-
saveStatus.id = 'save-status';
1122-
toolbar.appendChild(saveStatus);
1123-
1124-
this.updateSaveStatus = () => {
1125-
saveStatus.textContent = this.isDirty ? 'Unsaved changes' : 'Saved';
1126-
if (this.isDirty) {
1127-
saveStatus.classList.add('unsaved');
1128-
saveButton.classList.remove('secondary');
1129-
} else {
1130-
saveStatus.classList.remove('unsaved');
1131-
saveButton.classList.add('secondary');
1132-
}
1176+
const sendButtonIcon = document.createElement('span');
1177+
sendButtonIcon.classList.add('icon');
1178+
sendButtonIcon.textContent = 'send';
1179+
sendButton.appendChild(sendButtonIcon);
1180+
1181+
if (this.noFsMode) {
1182+
const sendButtonLabel = document.createElement('span');
1183+
sendButtonLabel.textContent = 'Send suggestion';
1184+
sendButton.appendChild(sendButtonLabel);
11331185
}
11341186

1135-
setInterval(() => {
1136-
this.updateSaveStatus();
1137-
}, 1000);
1187+
if (!this.noFsMode) {
1188+
const saveButton = document.createElement('button');
1189+
saveButton.classList.add('icon');
1190+
saveButton.classList.add('secondary');
1191+
saveButton.textContent = 'save';
1192+
saveButton.title = 'Save to Disk';
1193+
saveButton.addEventListener('click', () => this.save());
1194+
toolbar.appendChild(saveButton);
1195+
1196+
const saveStatus = document.createElement('span');
1197+
saveStatus.id = 'save-status';
1198+
toolbar.appendChild(saveStatus);
1199+
1200+
this.updateSaveStatus = () => {
1201+
saveStatus.textContent = this.isDirty ? 'Unsaved changes' : 'Saved';
1202+
if (this.isDirty) {
1203+
saveStatus.classList.add('unsaved');
1204+
saveButton.classList.remove('secondary');
1205+
} else {
1206+
saveStatus.classList.remove('unsaved');
1207+
saveButton.classList.add('secondary');
1208+
}
1209+
}
1210+
1211+
setInterval(() => {
1212+
this.updateSaveStatus();
1213+
}, 1000);
1214+
}
11381215
}
11391216

11401217
static constructContent() {

0 commit comments

Comments
 (0)
Please sign in to comment.