mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-06 02:30:47 -08:00
Add Go to URL dialog menu (#131)
This commit is contained in:
parent
06c9a4db24
commit
3e9ff738a6
14 changed files with 247 additions and 8 deletions
|
|
@ -11,6 +11,7 @@ const codeInjectionWindow = require('../windows/code-injection');
|
||||||
const customUserAgentWindow = require('../windows/custom-user-agent');
|
const customUserAgentWindow = require('../windows/custom-user-agent');
|
||||||
const displayMediaWindow = require('../windows/display-media');
|
const displayMediaWindow = require('../windows/display-media');
|
||||||
const editWorkspaceWindow = require('../windows/edit-workspace');
|
const editWorkspaceWindow = require('../windows/edit-workspace');
|
||||||
|
const goToUrlWindow = require('../windows/go-to-url');
|
||||||
const licenseRegistrationWindow = require('../windows/license-registration');
|
const licenseRegistrationWindow = require('../windows/license-registration');
|
||||||
const mainWindow = require('../windows/main');
|
const mainWindow = require('../windows/main');
|
||||||
const notificationsWindow = require('../windows/notifications');
|
const notificationsWindow = require('../windows/notifications');
|
||||||
|
|
@ -299,6 +300,19 @@ function createMenu() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Go To URL Window',
|
||||||
|
click: () => {
|
||||||
|
const win = goToUrlWindow.get();
|
||||||
|
if (win != null) {
|
||||||
|
if (win.webContents.isDevToolsOpened()) {
|
||||||
|
win.webContents.closeDevTools();
|
||||||
|
} else {
|
||||||
|
win.webContents.openDevTools({ mode: 'detach' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -339,6 +353,15 @@ function createMenu() {
|
||||||
},
|
},
|
||||||
enabled: hasWorkspaces,
|
enabled: hasWorkspaces,
|
||||||
},
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
|
{
|
||||||
|
label: 'Go to URL...',
|
||||||
|
accelerator: 'CmdOrCtrl+Shift+G',
|
||||||
|
click: () => {
|
||||||
|
goToUrlWindow.show();
|
||||||
|
},
|
||||||
|
enabled: hasWorkspaces,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
5
public/preload/go-to-url.js
Normal file
5
public/preload/go-to-url.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
window.mode = 'go-to-url';
|
||||||
|
|
||||||
|
const contextMenu = require('electron-context-menu');
|
||||||
|
|
||||||
|
contextMenu();
|
||||||
51
public/windows/go-to-url.js
Normal file
51
public/windows/go-to-url.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
const { BrowserWindow } = require('electron');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const { REACT_PATH } = require('../constants/paths');
|
||||||
|
const { getPreference } = require('../libs/preferences');
|
||||||
|
|
||||||
|
const mainWindow = require('./main');
|
||||||
|
|
||||||
|
let win;
|
||||||
|
|
||||||
|
const get = () => win;
|
||||||
|
|
||||||
|
const create = () => {
|
||||||
|
const attachToMenubar = getPreference('attachToMenubar');
|
||||||
|
|
||||||
|
win = new BrowserWindow({
|
||||||
|
width: 400,
|
||||||
|
height: 200,
|
||||||
|
resizable: false,
|
||||||
|
maximizable: false,
|
||||||
|
minimizable: false,
|
||||||
|
fullscreenable: false,
|
||||||
|
autoHideMenuBar: true,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
preload: path.join(__dirname, '..', 'preload', 'go-to-url.js'),
|
||||||
|
},
|
||||||
|
parent: attachToMenubar ? null : mainWindow.get(),
|
||||||
|
});
|
||||||
|
|
||||||
|
win.loadURL(REACT_PATH);
|
||||||
|
|
||||||
|
win.on('closed', () => {
|
||||||
|
win = null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const show = (url) => {
|
||||||
|
if (win == null) {
|
||||||
|
create(url);
|
||||||
|
} else {
|
||||||
|
win.close();
|
||||||
|
create(url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
get,
|
||||||
|
create,
|
||||||
|
show,
|
||||||
|
};
|
||||||
|
|
@ -122,9 +122,10 @@ const AddWorkspaceCustom = ({
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
id="outlined-full-width"
|
id="outlined-full-width"
|
||||||
label={nameError || 'Name'}
|
label="Name"
|
||||||
error={Boolean(nameError)}
|
error={Boolean(nameError)}
|
||||||
placeholder="Example: Singlebox"
|
placeholder="Example: Singlebox"
|
||||||
|
helperText={nameError}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
@ -137,9 +138,10 @@ const AddWorkspaceCustom = ({
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
id="outlined-full-width"
|
id="outlined-full-width"
|
||||||
label={homeUrlError || 'Home URL'}
|
label="Home URL"
|
||||||
error={Boolean(homeUrlError)}
|
error={Boolean(homeUrlError)}
|
||||||
placeholder="Example: https://singleboxapp.com"
|
placeholder="Example: https://singleboxapp.com"
|
||||||
|
helperText={homeUrlError || (isMailApp && 'Email app detected.')}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
@ -149,7 +151,6 @@ const AddWorkspaceCustom = ({
|
||||||
}}
|
}}
|
||||||
value={homeUrl}
|
value={homeUrl}
|
||||||
onChange={(e) => onUpdateForm({ homeUrl: e.target.value })}
|
onChange={(e) => onUpdateForm({ homeUrl: e.target.value })}
|
||||||
helperText={!homeUrlError && isMailApp && 'Email app detected.'}
|
|
||||||
/>
|
/>
|
||||||
<div className={classes.avatarFlex}>
|
<div className={classes.avatarFlex}>
|
||||||
<div className={classes.avatarLeft}>
|
<div className={classes.avatarLeft}>
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const CodeInjection = ({
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<div className={classes.flexGrow}>
|
<div className={classes.flexGrow}>
|
||||||
<TextField
|
<TextField
|
||||||
|
autoFocus
|
||||||
id="outlined-full-width"
|
id="outlined-full-width"
|
||||||
label="Code"
|
label="Code"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const CustomUserAgent = ({
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<div className={classes.flexGrow}>
|
<div className={classes.flexGrow}>
|
||||||
<TextField
|
<TextField
|
||||||
|
autoFocus
|
||||||
id="outlined-full-width"
|
id="outlined-full-width"
|
||||||
label="User-Agent"
|
label="User-Agent"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
|
|
||||||
|
|
@ -124,9 +124,10 @@ const EditWorkspace = ({
|
||||||
<div className={classes.flexGrow}>
|
<div className={classes.flexGrow}>
|
||||||
<TextField
|
<TextField
|
||||||
id="outlined-full-width"
|
id="outlined-full-width"
|
||||||
label={nameError || 'Name'}
|
label="Name"
|
||||||
error={Boolean(nameError)}
|
error={Boolean(nameError)}
|
||||||
placeholder="Optional"
|
placeholder="Optional"
|
||||||
|
helperText={nameError}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
@ -139,9 +140,10 @@ const EditWorkspace = ({
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
id="outlined-full-width"
|
id="outlined-full-width"
|
||||||
label={homeUrlError || 'Home URL'}
|
label="Home URL"
|
||||||
error={Boolean(homeUrlError)}
|
error={Boolean(homeUrlError)}
|
||||||
placeholder="Optional"
|
placeholder="Optional"
|
||||||
|
helperText={homeUrlError || (isMailApp && 'Email app detected.')}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
@ -151,7 +153,6 @@ const EditWorkspace = ({
|
||||||
}}
|
}}
|
||||||
value={homeUrl}
|
value={homeUrl}
|
||||||
onChange={(e) => onUpdateForm({ homeUrl: e.target.value })}
|
onChange={(e) => onUpdateForm({ homeUrl: e.target.value })}
|
||||||
helperText={!homeUrlError && isMailApp && 'Email app detected.'}
|
|
||||||
/>
|
/>
|
||||||
<div className={classes.avatarFlex}>
|
<div className={classes.avatarFlex}>
|
||||||
<div className={classes.avatarLeft}>
|
<div className={classes.avatarLeft}>
|
||||||
|
|
|
||||||
92
src/components/go-to-url/index.js
Normal file
92
src/components/go-to-url/index.js
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import TextField from '@material-ui/core/TextField';
|
||||||
|
|
||||||
|
import connectComponent from '../../helpers/connect-component';
|
||||||
|
|
||||||
|
import { updateForm, go } from '../../state/go-to-url/actions';
|
||||||
|
|
||||||
|
const styles = (theme) => ({
|
||||||
|
root: {
|
||||||
|
background: theme.palette.background.paper,
|
||||||
|
height: '100vh',
|
||||||
|
width: '100vw',
|
||||||
|
padding: theme.spacing.unit * 3,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
flexGrow: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
float: 'right',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const GoToUrl = ({
|
||||||
|
classes, url, urlError, onUpdateForm, onGo,
|
||||||
|
}) => (
|
||||||
|
<div className={classes.root}>
|
||||||
|
<div className={classes.flexGrow}>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
id="outlined-full-width"
|
||||||
|
label="URL"
|
||||||
|
error={Boolean(urlError)}
|
||||||
|
helperText={urlError}
|
||||||
|
placeholder="Type a URL"
|
||||||
|
fullWidth
|
||||||
|
margin="dense"
|
||||||
|
variant="outlined"
|
||||||
|
multiline={false}
|
||||||
|
InputLabelProps={{
|
||||||
|
shrink: true,
|
||||||
|
}}
|
||||||
|
value={url}
|
||||||
|
onChange={(e) => onUpdateForm({ url: e.target.value })}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
onGo();
|
||||||
|
e.target.blur();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button color="primary" variant="contained" className={classes.button} onClick={onGo}>
|
||||||
|
Go
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
GoToUrl.defaultProps = {
|
||||||
|
urlError: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
GoToUrl.propTypes = {
|
||||||
|
classes: PropTypes.object.isRequired,
|
||||||
|
url: PropTypes.string.isRequired,
|
||||||
|
urlError: PropTypes.string,
|
||||||
|
onUpdateForm: PropTypes.func.isRequired,
|
||||||
|
onGo: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
url: state.goToUrl.form.url,
|
||||||
|
urlError: state.goToUrl.form.urlError,
|
||||||
|
});
|
||||||
|
|
||||||
|
const actionCreators = {
|
||||||
|
updateForm,
|
||||||
|
go,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connectComponent(
|
||||||
|
GoToUrl,
|
||||||
|
mapStateToProps,
|
||||||
|
actionCreators,
|
||||||
|
styles,
|
||||||
|
);
|
||||||
|
|
@ -46,16 +46,17 @@ const DialogLicenseRegistration = (props) => {
|
||||||
perpetual license key ($9.99) from our store.
|
perpetual license key ($9.99) from our store.
|
||||||
</DialogContentText>
|
</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
|
autoFocus
|
||||||
fullWidth
|
fullWidth
|
||||||
id=""
|
id=""
|
||||||
label={licenseKeyError || 'License Key'}
|
label="License Key"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
onChange={(e) => onUpdateForm({ licenseKey: e.target.value })}
|
onChange={(e) => onUpdateForm({ licenseKey: e.target.value })}
|
||||||
value={licenseKey}
|
value={licenseKey}
|
||||||
placeholder="0-0000000000000-00000000-00000000-00000000-00000000"
|
placeholder="0-0000000000000-00000000-00000000-00000000-00000000"
|
||||||
error={Boolean(licenseKeyError)}
|
error={Boolean(licenseKeyError)}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
helperText="If you have already purchased Singlebox from our store, you should have received a license key via email to enter above."
|
helperText={licenseKeyError || 'If you have already purchased Singlebox from our store, you should have received a license key via email to enter above.'}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions className={classes.dialogActions}>
|
<DialogActions className={classes.dialogActions}>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ export const UPDATE_CODE_INJECTION_FORM = 'UPDATE_CODE_INJECTION_FORM';
|
||||||
// Custom User Agent
|
// Custom User Agent
|
||||||
export const UPDATE_CUSTOM_USER_AGENT_FORM = 'UPDATE_CUSTOM_USER_AGENT_FORM';
|
export const UPDATE_CUSTOM_USER_AGENT_FORM = 'UPDATE_CUSTOM_USER_AGENT_FORM';
|
||||||
|
|
||||||
|
// Go To URL
|
||||||
|
export const UPDATE_GO_TO_URL_FORM = 'UPDATE_GO_TO_URL_FORM';
|
||||||
|
|
||||||
// Auth
|
// Auth
|
||||||
export const UPDATE_AUTH_FORM = 'UPDATE_AUTH_FORM';
|
export const UPDATE_AUTH_FORM = 'UPDATE_AUTH_FORM';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ const CodeInjection = React.lazy(() => import('./components/code-injection'));
|
||||||
const CustomUserAgent = React.lazy(() => import('./components/custom-user-agent'));
|
const CustomUserAgent = React.lazy(() => import('./components/custom-user-agent'));
|
||||||
const DisplayMedia = React.lazy(() => import('./components/display-media'));
|
const DisplayMedia = React.lazy(() => import('./components/display-media'));
|
||||||
const EditWorkspace = React.lazy(() => import('./components/edit-workspace'));
|
const EditWorkspace = React.lazy(() => import('./components/edit-workspace'));
|
||||||
|
const GoToUrl = React.lazy(() => import('./components/go-to-url'));
|
||||||
const LicenseRegistration = React.lazy(() => import('./components/license-registration'));
|
const LicenseRegistration = React.lazy(() => import('./components/license-registration'));
|
||||||
const Main = React.lazy(() => import('./components/main'));
|
const Main = React.lazy(() => import('./components/main'));
|
||||||
const Notifications = React.lazy(() => import('./components/notifications'));
|
const Notifications = React.lazy(() => import('./components/notifications'));
|
||||||
|
|
@ -34,6 +35,7 @@ const App = () => {
|
||||||
case 'custom-user-agent': return <CustomUserAgent />;
|
case 'custom-user-agent': return <CustomUserAgent />;
|
||||||
case 'display-media': return <DisplayMedia />;
|
case 'display-media': return <DisplayMedia />;
|
||||||
case 'edit-workspace': return <EditWorkspace />;
|
case 'edit-workspace': return <EditWorkspace />;
|
||||||
|
case 'go-to-url': return <GoToUrl />;
|
||||||
case 'license-registration': return <LicenseRegistration />;
|
case 'license-registration': return <LicenseRegistration />;
|
||||||
case 'notifications': return <Notifications />;
|
case 'notifications': return <Notifications />;
|
||||||
case 'open-url-with': return <OpenUrlWith />;
|
case 'open-url-with': return <OpenUrlWith />;
|
||||||
|
|
@ -82,6 +84,8 @@ const runApp = () => {
|
||||||
document.title = 'Share your Screen';
|
document.title = 'Share your Screen';
|
||||||
} else if (window.mode === 'custom-user-agent') {
|
} else if (window.mode === 'custom-user-agent') {
|
||||||
document.title = 'Edit Custom User Agent';
|
document.title = 'Edit Custom User Agent';
|
||||||
|
} else if (window.mode === 'go-to-url') {
|
||||||
|
document.title = 'Go to URL';
|
||||||
} else {
|
} else {
|
||||||
document.title = 'Singlebox';
|
document.title = 'Singlebox';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
src/state/go-to-url/actions.js
Normal file
38
src/state/go-to-url/actions.js
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
import { UPDATE_GO_TO_URL_FORM } from '../../constants/actions';
|
||||||
|
import hasErrors from '../../helpers/has-errors';
|
||||||
|
import isUrl from '../../helpers/is-url';
|
||||||
|
import validate from '../../helpers/validate';
|
||||||
|
import { requestLoadUrl } from '../../senders';
|
||||||
|
|
||||||
|
const { remote } = window.require('electron');
|
||||||
|
|
||||||
|
|
||||||
|
const getValidationRules = () => ({
|
||||||
|
url: {
|
||||||
|
fieldName: 'URL',
|
||||||
|
required: true,
|
||||||
|
lessStrictUrl: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateForm = (changes) => (dispatch) => dispatch({
|
||||||
|
type: UPDATE_GO_TO_URL_FORM,
|
||||||
|
changes: validate(changes, getValidationRules()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const go = () => (dispatch, getState) => {
|
||||||
|
const { form } = getState().goToUrl;
|
||||||
|
|
||||||
|
const validatedChanges = validate(form, getValidationRules());
|
||||||
|
if (hasErrors(validatedChanges)) {
|
||||||
|
return dispatch(updateForm(validatedChanges));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { url } = form;
|
||||||
|
const finalUrl = isUrl(url) ? url : `http://${url}`;
|
||||||
|
|
||||||
|
requestLoadUrl(finalUrl);
|
||||||
|
remote.getCurrentWindow().close();
|
||||||
|
return null;
|
||||||
|
};
|
||||||
16
src/state/go-to-url/reducers.js
Normal file
16
src/state/go-to-url/reducers.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
|
import { UPDATE_GO_TO_URL_FORM } from '../../constants/actions';
|
||||||
|
|
||||||
|
const defaultForm = {
|
||||||
|
url: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = (state = defaultForm, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case UPDATE_GO_TO_URL_FORM: return { ...state, ...action.changes };
|
||||||
|
default: return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default combineReducers({ form });
|
||||||
|
|
@ -12,6 +12,7 @@ import customUserAgent from './custom-user-agent/reducers';
|
||||||
import editWorkspace from './edit-workspace/reducers';
|
import editWorkspace from './edit-workspace/reducers';
|
||||||
import findInPage from './find-in-page/reducers';
|
import findInPage from './find-in-page/reducers';
|
||||||
import general from './general/reducers';
|
import general from './general/reducers';
|
||||||
|
import goToUrl from './go-to-url/reducers';
|
||||||
import licenseRegistration from './license-registration/reducers';
|
import licenseRegistration from './license-registration/reducers';
|
||||||
import notifications from './notifications/reducers';
|
import notifications from './notifications/reducers';
|
||||||
import preferences from './preferences/reducers';
|
import preferences from './preferences/reducers';
|
||||||
|
|
@ -29,6 +30,7 @@ const rootReducer = combineReducers({
|
||||||
editWorkspace,
|
editWorkspace,
|
||||||
findInPage,
|
findInPage,
|
||||||
general,
|
general,
|
||||||
|
goToUrl,
|
||||||
licenseRegistration,
|
licenseRegistration,
|
||||||
notifications,
|
notifications,
|
||||||
preferences,
|
preferences,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue