Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add options page #158

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"rules": {
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-empty-interface": "off"
},
"env": {
"browser": true,
"es2021": true
}
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"rules": {
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-empty-interface": "off"
},
"env": {
"browser": true,
"es2021": true
}
}
1 change: 1 addition & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"48": "icons/48.png",
"128": "icons/128.png"
},
"options_page": "src/pages/options/index.html",
"content_scripts": [
{
"matches": ["*://*.steamcommunity.com/market/listings/730/*"],
Expand Down
2,254 changes: 2,168 additions & 86 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"@types/firefox-webext-browser": "^111.0.1",
"@types/jquery": "^3.5.14",
"@types/lodash": "^4.14.195",
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"copy-webpack-plugin": "^11.0.0",
Expand All @@ -41,20 +43,32 @@
"fast-json-stable-stringify": "^2.1.0",
"file-loader": "^6.2.0",
"filtrex": "^3.0.0",
"fs": "^0.0.1-security",
ayoung19 marked this conversation as resolved.
Show resolved Hide resolved
"glob": "^8.0.3",
"html-loader": "^4.1.0",
"html-webpack-plugin": "^5.5.3",
"ignore-loader": "^0.1.2",
"lit": "^2.3.0",
"lit-html": "^2.3.1",
"lodash": "^4.17.21",
"lodash-decorators": "^6.0.1",
"mini-css-extract-plugin": "^2.6.1",
"prettier": "^2.7.1",
"process": "^0.11.10",
"rxjs": "^7.5.7",
"sass-loader": "^13.0.2",
"ts-loader": "^9.3.1",
"typescript": "^4.7.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@mantine/core": "^6.0.17",
"@mantine/hooks": "^6.0.17",
"@tabler/icons-react": "^2.30.0",
"@tanstack/react-query": "^4.32.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
6 changes: 6 additions & 0 deletions src/lib/bridge/handlers/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import {FetchSkinModel} from './fetch_skin_model';
import {StorageRemove} from './storage_remove';
import {RequestType} from './types';
import {FetchExtensionFile} from './fetch_extension_file';
import {OpenOptionsPage} from './open_options_page';
import {SettingsGet} from './settings_get';
import {SettingsSet} from './settings_set';

export const HANDLERS_MAP: {[key in RequestType]: RequestHandler<any, any>} = {
[RequestType.EXECUTE_SCRIPT_ON_PAGE]: ExecuteScriptOnPage,
Expand All @@ -22,4 +25,7 @@ export const HANDLERS_MAP: {[key in RequestType]: RequestHandler<any, any>} = {
[RequestType.FETCH_PENDING_TRADES]: FetchPendingTrades,
[RequestType.FETCH_SKIN_MODEL]: FetchSkinModel,
[RequestType.FETCH_EXTENSION_FILE]: FetchExtensionFile,
[RequestType.OPEN_OPTIONS_PAGE]: OpenOptionsPage,
[RequestType.SETTINGS_GET]: SettingsGet,
[RequestType.SETTINGS_SET]: SettingsSet,
};
7 changes: 7 additions & 0 deletions src/lib/bridge/handlers/open_options_page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {RequestType} from './types';
import {runtimeNamespace} from '../../utils/detect';
import {EmptyRequestHandler} from './main';

export const OpenOptionsPage = new EmptyRequestHandler<void>(RequestType.OPEN_OPTIONS_PAGE, async () => {
return await runtimeNamespace().runtime.openOptionsPage();
});
38 changes: 38 additions & 0 deletions src/lib/bridge/handlers/settings_get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {RequestHandler} from '../types';
import {gStore} from '../../storage/store';
import {ClientSend} from '../client';
import {DynamicStorageKey, StorageKey, StorageRow} from '../../storage/keys';
import {RequestType} from './types';
import {GetSetting, Settings} from '../../../settings';

interface SettingsGetRequest<T extends keyof Settings> {
name: T;
}

interface SettingsGetResponse<T extends keyof Settings> {
value: Settings[T];
}

class SettingsGetHandler<T extends keyof Settings>
implements RequestHandler<SettingsGetRequest<T>, SettingsGetResponse<T>>
{
getType(): RequestType {
return RequestType.SETTINGS_GET;
}

async handleRequest(
request: SettingsGetRequest<T>,
sender: chrome.runtime.MessageSender
): Promise<SettingsGetResponse<T>> {
const value = await GetSetting(request.name);

return {value};
}
}

export async function Get<T extends keyof Settings>(name: T): Promise<Settings[T]> {
const resp = await ClientSend(new SettingsGetHandler<T>(), {name});
return resp.value;
}

export const SettingsGet = new SettingsGetHandler();
27 changes: 27 additions & 0 deletions src/lib/bridge/handlers/settings_set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {RequestHandler} from '../types';
import {gStore} from '../../storage/store';
import {ClientSend} from '../client';
import {DynamicStorageKey, StorageKey, StorageRow} from '../../storage/keys';
import {RequestType} from './types';
import {SetSetting, Settings} from '../../../settings';

interface SettingsSetRequest<T extends keyof Settings> {
name: T;
value: Settings[T];
}

class SettingsSetHandler<T extends keyof Settings> implements RequestHandler<SettingsSetRequest<T>, void> {
getType(): RequestType {
return RequestType.SETTINGS_SET;
}

async handleRequest(request: SettingsSetRequest<T>, sender: chrome.runtime.MessageSender): Promise<void> {
await SetSetting(request.name, request.value);
}
}

export async function Set<T extends keyof Settings>(name: T, value: Settings[T]): Promise<void> {
await ClientSend(new SettingsSetHandler<T>(), {name, value});
}

export const SettingsSet = new SettingsSetHandler();
3 changes: 3 additions & 0 deletions src/lib/bridge/handlers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ export enum RequestType {
FETCH_PENDING_TRADES,
FETCH_SKIN_MODEL,
FETCH_EXTENSION_FILE,
OPEN_OPTIONS_PAGE,
SETTINGS_GET,
SETTINGS_SET,
}
10 changes: 10 additions & 0 deletions src/lib/components/market/skin_viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {getMarketInspectLink} from './helpers';
import {rgAsset, ListingData} from '../../types/steam';
import {AppId, ContextId} from '../../types/steam_constants';
import {isSkin} from '../../utils/skin';
import {Get} from '../../bridge/handlers/settings_get';

enum Showing {
NONE,
Expand Down Expand Up @@ -74,8 +75,13 @@ export class SkinViewer extends FloatElement {
@state()
private showing: Showing = Showing.NONE;

@state()
private isEnabled = false;

async connectedCallback() {
super.connectedCallback();

this.isEnabled = await Get('3d-screenshot-buttons');
}

loadingIfApplicable(text: string, type: Showing) {
Expand All @@ -95,6 +101,10 @@ export class SkinViewer extends FloatElement {
return nothing;
}

if (!this.isEnabled) {
return nothing;
}

return html`
<div class="btn-container">
<csfloat-steam-button
Expand Down
47 changes: 44 additions & 3 deletions src/lib/components/market/utility_belt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import '../common/ui/steam-button';
import './page_size';
import './sort_listings';
import '../filter/filter_container';
import {ClientSend} from '../../bridge/client';
import {OpenOptionsPage} from '../../bridge/handlers/open_options_page';

@CustomElement()
@InjectBefore('#searchResultsRows', InjectionMode.ONCE)
Expand All @@ -22,6 +24,23 @@ export class UtilityBelt extends FloatElement {
background-color: rgba(0, 0, 0, 0.2);
}

.buttons-container {
display: flex;
align-items: center;
}

.settings-icon-wrapper {
padding: 4px;
margin-left: auto;
margin-right: 0;
border-radius: 4px;
display: inherit;
}

.settings-icon-wrapper:hover {
background-color: rgba(0, 0, 0, 0.3);
}

.page-selector {
margin-left: 10px;
}
Expand All @@ -37,9 +56,31 @@ export class UtilityBelt extends FloatElement {
protected render(): HTMLTemplateResult {
return html`
<div class="utility-container">
<csfloat-sort-listings></csfloat-sort-listings>
<csfloat-page-size class="page-selector"></csfloat-page-size>
<a class="github" href="https://csfloat.com" target="_blank">Powered by CSFloat</a>
<div class="buttons-container">
<csfloat-sort-listings></csfloat-sort-listings>
<csfloat-page-size class="page-selector"></csfloat-page-size>
<a class="github" href="https://csfloat.com" target="_blank">Powered by CSFloat</a>
<a class="settings-icon-wrapper" @click="${() => ClientSend(OpenOptionsPage, undefined)}">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon icon-tabler icon-tabler-settings"
width="16"
height="16"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z"
/>
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg>
</a>
</div>
<hr />
<csfloat-filter-container
?hidden="${!this.marketHashName}"
Expand Down
3 changes: 3 additions & 0 deletions src/lib/storage/keys.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/**
* Keys for use as the raw "key" in local/sync storage for a row
*/
import {StoredSettings} from '../../settings';
import {SerializedFilter} from '../filter/types';

export enum StorageKey {
// Backwards compatible with <3.0.0
PAGE_SIZE = 'pageSize',
ITEM_FILTERS = 'expressions',
GLOBAL_FILTERS = 'global',
SETTINGS = 'settings',
}

export type DynamicStorageKey = string;
Expand Down Expand Up @@ -45,3 +47,4 @@ export const PAGE_SIZE = newRow<number>(StorageKey.PAGE_SIZE);
// Dynamic prefixes should be the market hash name of the item
export const DYNAMIC_ITEM_FILTERS = newDynamicRow<SerializedFilter[]>(StorageKey.ITEM_FILTERS);
export const GLOBAL_FILTERS = newRow<SerializedFilter[]>(StorageKey.GLOBAL_FILTERS);
export const SETTINGS = newRow<StoredSettings>(StorageKey.SETTINGS);
72 changes: 72 additions & 0 deletions src/pages/options/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {
Button,
Card,
Divider,
Flex,
Group,
Image,
NavLink,
Space,
Stack,
Switch,
Tabs,
Text,
ThemeIcon,
Title,
UnstyledButton,
} from '@mantine/core';
import {AppShell, Navbar, Header} from '@mantine/core';
import {IconBackpack, IconBuildingStore, IconGitPullRequest, IconInfoCircle, IconSettings} from '@tabler/icons-react';
import {SettingsPage} from './settings/SettingsPage';
import {useState} from 'react';

const ALL_PAGE_IDS = ['settings'] as const;

type PageId = (typeof ALL_PAGE_IDS)[number];

const pageIdToComponent = (pageId: PageId) => {
switch (pageId) {
case 'settings':
return <SettingsPage />;
}
};

export const App = () => {
const [activePageId, setActivePageId] = useState<PageId>('settings');

return (
<AppShell
padding="md"
navbar={
<Navbar width={{base: 300}} p="xs">
<Flex direction="column" gap="xs">
<NavLink
label={<Text size="sm">Settings</Text>}
icon={
<ThemeIcon color="blue" variant="light">
<IconSettings size="1rem" />
</ThemeIcon>
}
variant="light"
active={activePageId === 'settings'}
onClick={() => setActivePageId('settings')}
/>
</Flex>
</Navbar>
}
header={
<Header height={60} p="xs">
<Group pl="md">
<Image width={130} src="https://csfloat.com/assets/n_full_logo.png" alt="CSFloat Logo" />
<Title order={2}>Market Checker</Title>
</Group>
</Header>
}
styles={(theme) => ({
main: {backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0]},
})}
>
{pageIdToComponent(activePageId)}
</AppShell>
);
};
Loading