diff --git a/src/components/modals/main/settings/sections/Message.jsx b/src/components/modals/main/settings/sections/Message.jsx
index f4a9e32a..fda8e83c 100644
--- a/src/components/modals/main/settings/sections/Message.jsx
+++ b/src/components/modals/main/settings/sections/Message.jsx
@@ -105,6 +105,7 @@ export default class Message extends PureComponent {
className="deleteButton"
onClick={() => this.modifyMessage('remove', index)}
>
+ Remove
diff --git a/src/components/modals/main/settings/sections/QuickLinks.jsx b/src/components/modals/main/settings/sections/QuickLinks.jsx
index 60d26df4..680f2e61 100644
--- a/src/components/modals/main/settings/sections/QuickLinks.jsx
+++ b/src/components/modals/main/settings/sections/QuickLinks.jsx
@@ -1,53 +1,319 @@
import variables from 'modules/variables';
-import { useState } from 'react';
-
+import { PureComponent, createRef } from 'react';
+import { TextareaAutosize } from '@mui/material';
+import { MdAddLink, MdLinkOff, MdClose, MdCancel, MdEdit } from 'react-icons/md';
import Header from '../Header';
import Checkbox from '../Checkbox';
+import Dropdown from '../Dropdown';
+import Modal from 'react-modal';
import SettingsItem from '../SettingsItem';
-export default function QuickLinks() {
- const [textOnly, setTextOnly] = useState(localStorage.getItem('quicklinksText') === 'true');
+import Tooltip from 'components/helpers/tooltip/Tooltip';
- return (
- <>
-
-
- i.key !== key);
+
+ localStorage.setItem('quicklinks', JSON.stringify(data));
+ this.setState({
+ items: data,
+ });
+
+ variables.stats.postEvent('feature', 'Quicklink delete');
+ }
+
+ addLink = () => {
+ const data = JSON.parse(localStorage.getItem('quicklinks'));
+ let url = this.state.url;
+ let urlError;
+
+ // regex: https://ihateregex.io/expr/url/
+ // eslint-disable-next-line no-useless-escape
+ if (
+ url.length <= 0 ||
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_.~#?&=]*)/.test(
+ url,
+ ) === false
+ ) {
+ urlError = variables.getMessage('widgets.quicklinks.url_error');
+ }
+
+ if (urlError) {
+ return this.setState({
+ urlError,
+ });
+ }
+
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
+ url = 'http://' + url;
+ }
+
+ data.push({
+ name: this.state.name || url,
+ url,
+ icon: this.state.icon || '',
+ key: Math.random().toString(36).substring(7) + 1,
+ });
+
+ localStorage.setItem('quicklinks', JSON.stringify(data));
+
+ this.setState({
+ items: data,
+ name: '',
+ url: '',
+ });
+
+ variables.stats.postEvent('feature', 'Quicklink add');
+
+ this.toggleAdd();
+
+ // make sure image is correct size
+ this.setZoom(this.quicklinksContainer.current);
+ };
+
+ toggleAdd = () => {
+ this.setState({
+ showAddModal: this.state.showAddLink === 'false' ? 'true' : 'false',
+ });
+ };
+
+ // widget zoom
+ setZoom(element) {
+ const zoom = localStorage.getItem('zoomQuicklinks') || 100;
+ if (localStorage.getItem('quicklinksText')) {
+ for (const link of element.getElementsByTagName('a')) {
+ link.style.fontSize = `${1.4 * Number(zoom / 100)}em`;
+ }
+ } else {
+ for (const img of element.getElementsByTagName('img')) {
+ img.style.height = `${1.4 * Number(zoom / 100)}em`;
+ }
+ }
+ }
+
+ componentDidMount() {
+ EventBus.on('refresh', (data) => {
+ if (data === 'quicklinks') {
+ if (localStorage.getItem('quicklinksenabled') === 'false') {
+ return (this.quicklinksContainer.current.style.display = 'none');
+ }
+
+ this.quicklinksContainer.current.style.display = 'block';
+ this.setZoom(this.quicklinksContainer.current);
+
+ this.setState({
+ items: JSON.parse(localStorage.getItem('quicklinks')),
+ });
+ }
+ });
+
+ this.setZoom(this.quicklinksContainer.current);
+ }
+
+ // allows you to add a link by pressing enter
+ topbarEnter = (e) => {
+ e = e || window.event;
+ const code = e.which || e.keyCode;
+ if (code === 13 && this.state.showAddLink === 'visible') {
+ this.addLink();
+ e.preventDefault();
+ }
+ };
+
+ componentWillUnmount() {
+ EventBus.off('refresh');
+ }
+
+ render() {
+ let target,
+ rel = null;
+ if (localStorage.getItem('quicklinksnewtab') === 'true') {
+ target = '_blank';
+ rel = 'noopener noreferrer';
+ }
+
+ const tooltipEnabled = localStorage.getItem('quicklinkstooltip');
+ const useProxy = localStorage.getItem('quicklinksddgProxy') !== 'false';
+ const useText = localStorage.getItem('quicklinksText') === 'true';
+
+ const quickLink = (item) => {
+ if (useText) {
+ return (
+ this.deleteLink(item.key, e)}
+ href={item.url}
+ target={target}
+ rel={rel}
+ draggable={false}
+ >
+ {item.name}
+
+ );
+ }
+
+ const url = useProxy
+ ? 'https://icons.duckduckgo.com/ip2/'
+ : 'https://www.google.com/s2/favicons?sz=32&domain=';
+ const img =
+ item.icon ||
+ url + item.url.replace('https://', '').replace('http://', '') + (useProxy ? '.ico' : '');
+
+ const link = (
+
+
+

+
+
+
{item.name}
+
{item.url}
+
+
+
+
+
+
+
+
+ );
+ return link;
+ };
+
+ return (
+ <>
+ setTextOnly(value)}
+ element=".quicklinks-container"
+ zoomSetting="zoomQuicklinks"
+ switch={true}
/>
-
-
-
-
- >
- );
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.state.items.length === 0 ? (
+
+
+
+ No quicklinks
+
+ {variables.getMessage('modals.main.settings.sections.message.add_some')}
+
+
+
+
+ ) : null}
+
+
+ {this.state.items.map((item) => quickLink(item))}
+
+ this.setState({ showAddModal: false })}
+ isOpen={this.state.showAddModal}
+ className="Modal resetmodal mainModal"
+ overlayClassName="Overlay resetoverlay"
+ ariaHideApp={false}
+ >
+
+
+
{variables.getMessage('widgets.quicklinks.new')}
+
+ this.setState({ showAddModal: false })}>
+
+
+
+
+
+ this.setState({ name: e.target.value })}
+ />
+
+ this.setState({ url: e.target.value })}
+ />
+ {this.state.urlError}
+ this.setState({ icon: e.target.value })}
+ />
+
+
+
+
+
+ >
+ );
+ }
}
diff --git a/src/components/widgets/quicklinks/QuickLinks.jsx b/src/components/widgets/quicklinks/QuickLinks.jsx
index e3cbbb5e..2e78448b 100644
--- a/src/components/widgets/quicklinks/QuickLinks.jsx
+++ b/src/components/widgets/quicklinks/QuickLinks.jsx
@@ -101,7 +101,7 @@ export default class QuickLinks extends PureComponent {
}
} else {
for (const img of element.getElementsByTagName('img')) {
- img.style.height = `${1.4 * Number(zoom / 100)}em`;
+ img.style.height = `${30 * Number(zoom / 100)}px`;
}
}
}
@@ -149,15 +149,13 @@ export default class QuickLinks extends PureComponent {
const tooltipEnabled = localStorage.getItem('quicklinkstooltip');
const useProxy = localStorage.getItem('quicklinksddgProxy') !== 'false';
- const useText = localStorage.getItem('quicklinksText') === 'true';
const quickLink = (item) => {
- if (useText) {
+ if (localStorage.getItem('quickLinksStyle') === 'text') {
return (
this.deleteLink(item.key, e)}
href={item.url}
target={target}
rel={rel}
@@ -175,10 +173,25 @@ export default class QuickLinks extends PureComponent {
item.icon ||
url + item.url.replace('https://', '').replace('http://', '') + (useProxy ? '.ico' : '');
+ if (localStorage.getItem('quickLinksStyle') === 'metro') {
+ return (
+
+
+ {item.name}
+
+ );
+ }
+
const link = (
this.deleteLink(item.key, e)}
href={item.url}
target={target}
rel={rel}
@@ -189,7 +202,7 @@ export default class QuickLinks extends PureComponent {
);
return tooltipEnabled === 'true' ? (
-
+
{link}
) : (
@@ -202,11 +215,6 @@ export default class QuickLinks extends PureComponent {
{this.state.items.map((item) => quickLink(item))}
-
-
-
) : (
@@ -223,8 +223,8 @@ export default class Search extends PureComponent {
- {localStorage.getItem('searchDropdown') === 'true' ? (
-
+ {localStorage.getItem('searchDropdown') === 'true' && this.state.searchDropdown === true ? (
+
{searchEngines.map(({ name }) => {
if (name === this.state.currentSearch) {
return null;