Skip to content

Commit

Permalink
feat: Copy/paste settings through UI
Browse files Browse the repository at this point in the history
  • Loading branch information
oliversalzburg committed Nov 16, 2022
1 parent 0f21120 commit 14b8040
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 7 deletions.
24 changes: 21 additions & 3 deletions packages/userscript/source/UserScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ declare global {
const KS_VERSION: string | null;
let unsafeWindow: Window | undefined;
interface Window {
$: JQuery;
$I?: Maybe<I18nEngine>;
dojo: {
clone: <T>(subject: T) => T;
subscribe: (event: string, handler: (...args: any[]) => void) => void;
};
gamePage?: Maybe<GamePage>;
$: JQuery;
$I?: Maybe<I18nEngine>;
LZString: {
compressToBase64: (input: string) => string;
compressToUTF16: (input: string) => string;
decompressFromBase64: (input: string) => string;
decompressFromUTF16: (input: string) => string;
};
}
}

Expand Down Expand Up @@ -151,12 +157,24 @@ export class UserScript {
workshop: this.engine.workshopManager.settings,
});
}
getSettings() {
getSettings(): EngineState {
return this.engine.stateSerialize();
}
copySettings() {
const settings = this.getSettings();
const settingsString = JSON.stringify(settings);
const compressedSettings = window.LZString.compressToBase64(settingsString);
return window.navigator.clipboard.writeText(compressedSettings);
}
setSettings(settings: EngineState) {
cinfo("Loading engine state...");
this.engine.stateLoad(settings);
this._userInterface.refreshUi();
}
importSettings(compressedSettings: string) {
const settingsString = window.LZString.decompressFromBase64(compressedSettings);
const settings = JSON.parse(settingsString) as EngineState;
this.setSettings(settings);
}

installSaveManager() {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/userscript/source/settings/FilterSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ export class FilterSettings extends Setting {
this.enabled = settings.enabled;

for (const [name, item] of objectEntries(settings.filters)) {
if (!this.filters[name]) {
console.warn(`Outdated filter '${name}' is ignored on settings load.`);
continue;
}
this.filters[name].enabled = item.enabled;
}
}
Expand Down
15 changes: 15 additions & 0 deletions packages/userscript/source/ui/EngineSettingsUi.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { EngineSettings } from "../settings/EngineSettings";
import { ucfirst } from "../tools/Format";
import { UserScript } from "../UserScript";
import { CopyButton } from "./components/CopyButton";
import { ExpandoButton } from "./components/ExpandoButton";
import { ImportButton } from "./components/ImportButton";
import { SettingListItem } from "./components/SettingListItem";

export class EngineSettingsUi {
readonly copyButton: CopyButton;
readonly element: JQuery<HTMLElement>;
readonly expando: ExpandoButton;
readonly importButton: ImportButton;
private readonly _element: SettingListItem;
private readonly _settings: EngineSettings;

Expand All @@ -19,6 +25,15 @@ export class EngineSettingsUi {
onUnCheck: () => host.engine.stop(true),
});
this.element = this._element.element;

this.expando = new ExpandoButton(host);
this.element.append(this.expando.element);

this.copyButton = new CopyButton(host);
this.element.append(this.copyButton.element);

this.importButton = new ImportButton(host);
this.element.append(this.importButton.element);
}

setState(state: EngineSettings): void {
Expand Down
20 changes: 16 additions & 4 deletions packages/userscript/source/ui/UserInterface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { cinfo } from "../tools/Log";
import { isNil, mustExist } from "../tools/Maybe";
import { UserScript } from "../UserScript";
import { BonfireSettingsUi } from "./BonfireSettingsUi";
import { ExpandoButton } from "./components/ExpandoButton";
import { EngineSettingsUi } from "./EngineSettingsUi";
import { FiltersSettingsUi } from "./FilterSettingsUi";
import { OptionsSettingsUi } from "./OptionsSettingsUi";
Expand Down Expand Up @@ -78,10 +78,8 @@ export class UserInterface {
optionsListElement.append(this._optionsUi.element);
optionsListElement.append(this._filterUi.element);

const expando = new ExpandoButton(this._host);
this._engineUi.element.append(expando.element);

// Make _engineUI's expando button hide/show the other option groups
const expando = this._engineUi.expando;
let sectionsVisible = false;
expando.element.on("click", () => {
sectionsVisible = !sectionsVisible;
Expand All @@ -105,6 +103,20 @@ export class UserInterface {
this._filterUi.toggle(sectionsVisible);
});

const copyButton = this._engineUi.copyButton;
copyButton.element.on("click", () => {
this._host.copySettings().catch(console.error);
cinfo("Settings copied to clipboard.");
});
this._engineUi.importButton.element.on("click", () => {
const input = window.prompt("Settings BLOB");
if (isNil(input)) {
return;
}
this._host.importSettings(input);
cinfo("Settings imported.");
});

// Set up the "show activity summary" area.
const showActivity = $("<span/>", {
html: '<svg style="width: 15px; height: 15px;" viewBox="0 0 48 48"><path fill="currentColor" d="M15.45 16.95q.6 0 1.05-.45.45-.45.45-1.05 0-.6-.45-1.05-.45-.45-1.05-.45-.6 0-1.05.45-.45.45-.45 1.05 0 .6.45 1.05.45.45 1.05.45Zm0 8.55q.6 0 1.05-.45.45-.45.45-1.05 0-.6-.45-1.05-.45-.45-1.05-.45-.6 0-1.05.45-.45.45-.45 1.05 0 .6.45 1.05.45.45 1.05.45Zm0 8.55q.6 0 1.05-.45.45-.45.45-1.05 0-.6-.45-1.05-.45-.45-1.05-.45-.6 0-1.05.45-.45.45-.45 1.05 0 .6.45 1.05.45.45 1.05.45ZM9 42q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h23.1l9.9 9.9V39q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h30V17.55h-8.55V9H9v30ZM9 9v8.55V9v30V9Z"/></svg>',
Expand Down
25 changes: 25 additions & 0 deletions packages/userscript/source/ui/components/CopyButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { UserScript } from "../../UserScript";
import { UiComponent } from "./UiComponent";

/**
* A button that is intended to initiate a copy action.
*/
export class CopyButton extends UiComponent {
readonly element: JQuery<HTMLElement>;

/**
* Constructs a `CopyButton`.
*
* @param host A reference to the host.
*/
constructor(host: UserScript) {
super(host);

const element = $("<div/>", {
html: '<svg style="width: 15px; height: 15px;" viewBox="0 0 48 48"><path fill="currentColor" d="M9 43.95q-1.2 0-2.1-.9-.9-.9-.9-2.1V10.8h3v30.15h23.7v3Zm6-6q-1.2 0-2.1-.9-.9-.9-.9-2.1v-28q0-1.2.9-2.1.9-.9 2.1-.9h22q1.2 0 2.1.9.9.9.9 2.1v28q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h22v-28H15v28Zm0 0v-28 28Z"/></svg>',
title: "Copy to clipboard",
}).addClass("ks-icon-button");

this.element = element;
}
}
25 changes: 25 additions & 0 deletions packages/userscript/source/ui/components/ImportButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { UserScript } from "../../UserScript";
import { UiComponent } from "./UiComponent";

/**
* A button that is intended to initiate an import action.
*/
export class ImportButton extends UiComponent {
readonly element: JQuery<HTMLElement>;

/**
* Constructs a `ImportButton`.
*
* @param host A reference to the host.
*/
constructor(host: UserScript) {
super(host);

const element = $("<div/>", {
html: '<svg style="width: 15px; height: 15px;" viewBox="0 0 48 48"><path fill="currentColor" d="M22.5 40V21.45l-6 6-2.15-2.15L24 15.65l9.65 9.65-2.15 2.15-6-6V40ZM8 18.15V11q0-1.2.9-2.1Q9.8 8 11 8h26q1.2 0 2.1.9.9.9.9 2.1v7.15h-3V11H11v7.15Z"/></svg>',
title: "Import",
}).addClass("ks-icon-button");

this.element = element;
}
}

0 comments on commit 14b8040

Please sign in to comment.