mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
add link buttons to drawer, ditch dropdown button for subscribe
This commit is contained in:
parent
7546c7e655
commit
60711b53e4
7 changed files with 144 additions and 116 deletions
23
src/FilterLists.Web.V2/src/components/LinkButton.tsx
Normal file
23
src/FilterLists.Web.V2/src/components/LinkButton.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { Button } from 'antd';
|
||||
import { ButtonType } from 'antd/lib/button';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
url: string;
|
||||
text: string;
|
||||
title?: string;
|
||||
type?: ButtonType;
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
export const LinkButton = (props: Props) =>
|
||||
<Button
|
||||
href={props.url}
|
||||
title={props.title}
|
||||
type={props.type || "default"}
|
||||
block
|
||||
style={{ borderLeftColor: "rgb(217, 217, 217)" }} //HACK: override buggy style in antd
|
||||
icon={props.icon}
|
||||
target="_blank" rel="noopener noreferrer" >
|
||||
{props.text}
|
||||
</Button >;
|
||||
|
|
@ -11,6 +11,7 @@ interface Props {
|
|||
export const ListDetailsButton = (props: RouteComponentProps & Props) =>
|
||||
<Button
|
||||
type="primary"
|
||||
icon="info-circle"
|
||||
onClick={() => props.history.push(`/lists/${props.list.id}`)}>
|
||||
Details
|
||||
</Button>;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { Drawer } from 'antd';
|
||||
import { Divider, Drawer } from 'antd';
|
||||
import ButtonGroup from 'antd/lib/button/button-group';
|
||||
import React from 'react';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
|
|
@ -7,7 +8,8 @@ import { List } from '../interfaces/List';
|
|||
import { Tag } from '../interfaces/Tag';
|
||||
import { Description } from './Description';
|
||||
import { LanguageCloud } from './languageCloud';
|
||||
import { SubscribeButton } from './subscribeButton';
|
||||
import { LinkButton } from './LinkButton';
|
||||
import { SubscribeButton } from './SubscribeButton';
|
||||
import { TagCloud } from './tagCloud';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -46,7 +48,55 @@ export class ListDetailsDrawer extends React.Component<RouteComponentProps & Pro
|
|||
{this.props.list.tagIds
|
||||
? <TagCloud tags={this.props.tags.filter((t: Tag) => this.props.list.tagIds.includes(t.id))} showLabel={true} />
|
||||
: null}
|
||||
<SubscribeButton {...this.props.list} />
|
||||
<Divider />
|
||||
<ButtonGroup style={{ display: "inherit" }}>
|
||||
{this.props.list.viewUrl && <SubscribeButton {...this.props.list} />}
|
||||
{this.props.list.viewUrl &&
|
||||
<LinkButton url={this.props.list.viewUrl}
|
||||
text="View"
|
||||
title={`View ${this.props.list.name} in its raw format`}
|
||||
icon="search" />}
|
||||
{this.props.list.homeUrl &&
|
||||
<LinkButton url={this.props.list.homeUrl}
|
||||
text="Home"
|
||||
title={`View ${this.props.list.name}'s homepage.`}
|
||||
icon="home" />}
|
||||
{this.props.list.policyUrl &&
|
||||
<LinkButton url={this.props.list.policyUrl}
|
||||
text="Policy"
|
||||
title={`View the types of rules that ${this.props.list.name} includes.`}
|
||||
icon="file-exclamation" />}
|
||||
{this.props.list.emailAddress &&
|
||||
<LinkButton url={`mailto:${this.props.list.emailAddress}`}
|
||||
text="Email"
|
||||
title={`Email ${this.props.list.name}.`}
|
||||
icon="mail" />}
|
||||
{this.props.list.issuesUrl &&
|
||||
<LinkButton url={this.props.list.issuesUrl}
|
||||
text="GitHub Issues"
|
||||
title={`View the GitHub Issues for ${this.props.list.name}.`}
|
||||
icon="github" />}
|
||||
{this.props.list.submissionUrl &&
|
||||
<LinkButton url={this.props.list.submissionUrl}
|
||||
text="Submit a Rule"
|
||||
title={`Submit a new rule to be included in ${this.props.list.name}.`}
|
||||
icon="form" />}
|
||||
{this.props.list.forumUrl &&
|
||||
<LinkButton url={this.props.list.forumUrl}
|
||||
text="Forum"
|
||||
title={`View the forum for ${this.props.list.name}.`}
|
||||
icon="team" />}
|
||||
{this.props.list.chatUrl &&
|
||||
<LinkButton url={this.props.list.chatUrl}
|
||||
text="Chat"
|
||||
title={`Enter the chat room for ${this.props.list.name}.`}
|
||||
icon="message" />}
|
||||
{this.props.list.donateUrl &&
|
||||
<LinkButton url={this.props.list.donateUrl}
|
||||
text="Donate"
|
||||
title={`Donate to the maintainer of ${this.props.list.name}.`}
|
||||
icon="dollar" />}
|
||||
</ButtonGroup>
|
||||
</Drawer>
|
||||
}
|
||||
|
||||
|
|
|
|||
67
src/FilterLists.Web.V2/src/components/SubscribeButton.tsx
Normal file
67
src/FilterLists.Web.V2/src/components/SubscribeButton.tsx
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import { Button } from 'antd';
|
||||
import { ButtonProps, ButtonType } from 'antd/lib/button';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
viewUrl: string;
|
||||
viewUrlMirrors: string[];
|
||||
};
|
||||
|
||||
export const SubscribeButton = (props: Props): JSX.Element => {
|
||||
const buttonProps = buildButtonProps(props.name, props.viewUrl);
|
||||
return <span>
|
||||
<Button disabled={buttonProps[1]}
|
||||
block
|
||||
icon="import"
|
||||
{...buttonProps[0]}>
|
||||
Subscribe
|
||||
</Button>
|
||||
{props.viewUrlMirrors && props.viewUrlMirrors.length &&
|
||||
props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => {
|
||||
const buttonProps = buildButtonProps(props.name, viewUrlMirror);
|
||||
return <Button key={i}
|
||||
disabled={buttonProps[1]}
|
||||
block
|
||||
icon="import"
|
||||
{...buttonProps[0]}>
|
||||
{`Mirror ${i + 1} Subscribe`}
|
||||
</Button>
|
||||
})}
|
||||
</span>
|
||||
};
|
||||
|
||||
const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => {
|
||||
let type: ButtonType = "primary";
|
||||
let disabled: boolean = false;
|
||||
|
||||
const hrefLocation = `${encodeURIComponent(viewUrl)}`;
|
||||
const hrefTitle = `${encodeURIComponent(name)}`;
|
||||
let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`;
|
||||
|
||||
let prefixes: string[] = [];
|
||||
let message = `Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`;
|
||||
|
||||
// HTTP protocols
|
||||
if (viewUrl.includes(".onion/")) {
|
||||
type = "dashed";
|
||||
prefixes.push("TOR");
|
||||
}
|
||||
if (viewUrl.includes("http://")) {
|
||||
type = "danger";
|
||||
prefixes.push("INSECURE");
|
||||
}
|
||||
|
||||
// Software protocols
|
||||
if (viewUrl.includes(".tpl")) {
|
||||
disabled = true; // IE not supported by FilterLists
|
||||
}
|
||||
if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) {
|
||||
href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`;
|
||||
message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`;
|
||||
}
|
||||
|
||||
const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`;
|
||||
|
||||
return [{ type, href, title }, disabled]
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
.sub_li {
|
||||
/* reduce vertical white space around dropdown items */
|
||||
height: 24px !important;
|
||||
}
|
||||
|
||||
.sub_a {
|
||||
/* fix font color on dropdown buttons */
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.single {
|
||||
/* make non-dropdown button equivalent width to dropdown */
|
||||
width: 106.81px;
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
import { Button, Dropdown, Menu } from 'antd';
|
||||
import { ButtonProps, ButtonType } from 'antd/lib/button';
|
||||
import React from 'react';
|
||||
|
||||
import styles from './SubscribeButton.module.css';
|
||||
|
||||
//TODO: import DropdownButtonType from antd rather than redefining if they export the type
|
||||
//import { DropdownButtonType } from "antd/lib/dropdown";
|
||||
declare type DropdownButtonType = 'primary' | 'ghost' | 'dashed';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
viewUrl: string;
|
||||
viewUrlMirrors: string[];
|
||||
};
|
||||
|
||||
export const SubscribeButton = (props: Props): JSX.Element => {
|
||||
const buttonProps = buildButtonProps(props.name, props.viewUrl);
|
||||
return (props.viewUrlMirrors && props.viewUrlMirrors.length)
|
||||
? <ButtonDropdown {...props} />
|
||||
: <div>
|
||||
<Button disabled={buttonProps[1]}
|
||||
className={styles.single} size="small"
|
||||
{...buttonProps[0]}>
|
||||
Subscribe
|
||||
</Button>
|
||||
</div>
|
||||
};
|
||||
|
||||
const ButtonDropdown = (props: Props): JSX.Element => {
|
||||
const buttonProps = buildButtonProps(props.name, props.viewUrl);
|
||||
return <Dropdown.Button
|
||||
disabled={buttonProps[1]}
|
||||
size="small"
|
||||
placement="bottomRight"
|
||||
type={buttonProps[0].type as DropdownButtonType}
|
||||
href={buttonProps[0].href}
|
||||
title={buttonProps[0].title}
|
||||
overlay={<DropdownOverlay viewUrlMirrors={props.viewUrlMirrors} name={props.name} />}>
|
||||
Subscribe
|
||||
</Dropdown.Button>;
|
||||
};
|
||||
|
||||
interface DropdownOverlayProps {
|
||||
name: string;
|
||||
viewUrlMirrors: string[];
|
||||
};
|
||||
|
||||
const DropdownOverlay = (props: DropdownOverlayProps): JSX.Element =>
|
||||
<Menu>
|
||||
{props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => {
|
||||
const buttonProps = buildButtonProps(props.name, viewUrlMirror);
|
||||
return <Menu.Item className={styles.sub_li} key={i}>
|
||||
<Button disabled={buttonProps[1]}
|
||||
className={styles.sub_a} size="small"
|
||||
{...buttonProps[0]}>
|
||||
{`Mirror ${i + 1}`}
|
||||
</Button>
|
||||
</Menu.Item>
|
||||
})}
|
||||
</Menu>;
|
||||
|
||||
const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => {
|
||||
let type: ButtonType = "primary";
|
||||
let disabled: boolean = false;
|
||||
|
||||
const hrefLocation = `${encodeURIComponent(viewUrl)}`;
|
||||
const hrefTitle = `${encodeURIComponent(name)}`;
|
||||
let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`;
|
||||
|
||||
let prefixes: string[] = [];
|
||||
let message = `Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`;
|
||||
|
||||
// HTTP protocols
|
||||
if (viewUrl.includes(".onion/")) {
|
||||
type = "dashed";
|
||||
prefixes.push("TOR");
|
||||
}
|
||||
if (viewUrl.includes("http://")) {
|
||||
type = "danger";
|
||||
prefixes.push("INSECURE");
|
||||
}
|
||||
|
||||
// Software protocols
|
||||
if (viewUrl.includes(".tpl")) {
|
||||
disabled = true; // IE not supported by FilterLists
|
||||
}
|
||||
if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) {
|
||||
href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`;
|
||||
message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`;
|
||||
}
|
||||
|
||||
const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`;
|
||||
|
||||
return [{ type, href, title }, disabled]
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { SubscribeButton } from './SubscribeButton';
|
||||
|
||||
export { SubscribeButton }
|
||||
Loading…
Reference in a new issue