1
Fork 0

Feature: Add import and export settings buttons (fixes #2)

This commit is contained in:
Bauke 2019-11-11 15:40:30 +01:00
parent 2203cb0f90
commit b063e1507c
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
6 changed files with 161 additions and 0 deletions

View File

@ -74,8 +74,10 @@
"ts" "ts"
], ],
"global": [ "global": [
"Blob",
"confirm", "confirm",
"document", "document",
"FileReader",
"performance", "performance",
"window" "window"
], ],

View File

@ -5,6 +5,7 @@
"description": "An updated and reimagined recreation of Tildes Extended to enhance and improve the experience of Tildes.net.", "description": "An updated and reimagined recreation of Tildes Extended to enhance and improve the experience of Tildes.net.",
"version": "0.1.1", "version": "0.1.1",
"permissions": [ "permissions": [
"downloads",
"storage", "storage",
"*://tildes.net/*" "*://tildes.net/*"
], ],

View File

@ -157,6 +157,16 @@
please use the "Copy Bug Template" button below and fill out please use the "Copy Bug Template" button below and fill out
the template in your message. the template in your message.
</p> </p>
<form id="import-export">
<input class="trx-hidden" accept="application/json" type="file"
id="import-file">
<button id="import-button">Import Settings</button>
<button id="export-button">Export Settings</button>
</form>
<p>
When importing settings, note that your current settings will be
deleted and overwritten with the new ones.
</p>
</div> </div>
<div id="debug-buttons"> <div id="debug-buttons">
<button id="copy-bug-template-button"> <button id="copy-bug-template-button">

View File

@ -200,6 +200,28 @@ p > .red-re {
} }
} }
#import-export {
align-items: center;
display: flex;
justify-content: center;
margin-bottom: 1rem;
> button {
border: none;
color: $foreground;
background-color: $cyan;
padding: 1rem;
&:hover {
background-color: darken($cyan, 10%);
}
&:last-child {
margin-left: 1rem;
}
}
}
#footer { #footer {
align-items: center; align-items: center;
display: flex; display: flex;

108
source/ts/import-export.ts Normal file
View File

@ -0,0 +1,108 @@
import {browser} from 'webextension-polyfill-ts';
import {
querySelector,
flashMessage,
Settings,
log,
getSettings,
isValidTildesUsername,
isValidHexColor,
setSettings
} from './utilities';
import {themeColors} from './theme-colors';
export async function importSettingsHandler(event: MouseEvent): Promise<void> {
event.preventDefault();
const fileInput: HTMLInputElement = querySelector('#import-file');
fileInput.click();
}
export async function importFileHandler(event: Event): Promise<void> {
const fileList: FileList | null = (event.target as HTMLInputElement).files;
if (fileList === null) {
flashMessage('No file imported.');
return;
}
const reader: FileReader = new FileReader();
reader.addEventListener(
'load',
async (): Promise<void> => {
let data: Partial<Settings>;
try {
data = JSON.parse(reader.result!.toString());
} catch (error) {
log(error, true);
flashMessage(error, true);
return;
}
const settings: Settings = await getSettings();
const newSettings: Settings = {...settings};
if (typeof data.data !== 'undefined') {
if (typeof data.data.userLabels !== 'undefined') {
newSettings.data.userLabels = [];
for (const label of data.data.userLabels) {
if (
typeof label.username === 'undefined' ||
!isValidTildesUsername(label.username)
) {
log(`Invalid username in imported labels: ${label.username}`);
continue;
}
newSettings.data.userLabels.push({
color: isValidHexColor(label.color)
? label.color
: themeColors.white.backgroundAlt,
id: newSettings.data.userLabels.length + 1,
priority: isNaN(label.priority) ? 0 : label.priority,
text: typeof label.text === 'undefined' ? 'Label' : label.text,
username: label.username
});
}
}
}
if (typeof data.features !== 'undefined') {
newSettings.features = {...data.features};
}
await setSettings(newSettings);
flashMessage(
'Successfully imported your settings, reloading the page to apply.'
);
setTimeout(() => {
window.location.reload();
}, 2500);
}
);
reader.addEventListener('error', (): void => {
log(reader.error, true);
reader.abort();
});
reader.readAsText(fileList[0]);
}
export async function exportSettingsHandler(event: MouseEvent): Promise<void> {
event.preventDefault();
const settings: Settings = await getSettings();
const settingsBlob: Blob = new Blob([JSON.stringify(settings, null, 2)], {
type: 'text/json'
});
const blobObjectURL: string = URL.createObjectURL(settingsBlob);
try {
await browser.downloads.download({
filename: 'tildes_reextended-settings.json',
url: blobObjectURL,
saveAs: true
});
} catch (error) {
log(error);
} finally {
// According to MDN, when creating an object URL we should also revoke it
// when "it's safe to do so" to prevent excess memory/storage use. 60
// seconds should be enough time to download the settings.
setTimeout(() => URL.revokeObjectURL(blobObjectURL), 60000);
}
}

View File

@ -1,5 +1,10 @@
import platform from 'platform'; import platform from 'platform';
import {browser} from 'webextension-polyfill-ts'; import {browser} from 'webextension-polyfill-ts';
import {
importSettingsHandler,
importFileHandler,
exportSettingsHandler
} from './import-export';
import { import {
getSettings, getSettings,
Settings, Settings,
@ -33,6 +38,19 @@ window.addEventListener(
) )
); );
const importSettingsButton: HTMLButtonElement = querySelector(
'#import-button'
);
importSettingsButton.addEventListener('click', importSettingsHandler);
const importFileInput: HTMLInputElement = querySelector('#import-file');
importFileInput.addEventListener('change', importFileHandler);
const exportSettingsButton: HTMLButtonElement = querySelector(
'#export-button'
);
exportSettingsButton.addEventListener('click', exportSettingsHandler);
const copyBugTemplateButton: HTMLButtonElement = querySelector( const copyBugTemplateButton: HTMLButtonElement = querySelector(
'#copy-bug-template-button' '#copy-bug-template-button'
); );