├── .gitignore ├── desktop-app ├── .nvmrc ├── app │ ├── utils │ │ ├── .gitkeep │ │ ├── stringUtils.js │ │ ├── urlUtils.js │ │ ├── logUtils.js │ │ ├── browserUtils.js │ │ ├── filterUtils.js │ │ ├── navigatorUtils.js │ │ ├── iconUtils.js │ │ ├── proxyUtils.js │ │ ├── analytics.js │ │ ├── generalUtils.js │ │ ├── TextAreaWithCopyButton.js │ │ └── browserSync.js │ ├── constants │ │ ├── routes.js │ │ ├── searchResultSettings.js │ │ ├── theme.js │ │ ├── license.js │ │ ├── browserSync.js │ │ ├── values.js │ │ ├── permissionsManagement.js │ │ ├── previewerLayouts.js │ │ ├── DrawerContents.js │ │ ├── index.js │ │ ├── settingKeys.js │ │ └── pubsubEvents.js │ ├── app.icns │ ├── components │ │ ├── DeviceDrawer │ │ │ ├── styles.css │ │ │ └── index.js │ │ ├── NetworkConfiguration │ │ │ ├── styles.css │ │ │ └── index.js │ │ ├── ZoomInput │ │ │ ├── otherStyles.css │ │ │ ├── styles.module.css │ │ │ └── index.test.js │ │ ├── ScreenshotManager │ │ │ └── index.js │ │ ├── NetworkThrottling │ │ │ ├── styles.css │ │ │ └── ProfileManager │ │ │ │ └── styles.css │ │ ├── ExtensionsManager │ │ │ ├── help-screenshot.png │ │ │ └── styles.css │ │ ├── icons │ │ │ ├── styles.module.css │ │ │ ├── Logo.js │ │ │ ├── Chevron.js │ │ │ ├── Reload.js │ │ │ ├── ArrowLeft.js │ │ │ ├── ArrowRight.js │ │ │ ├── Windows.js │ │ │ ├── CrossChrome.js │ │ │ ├── GoArrow.js │ │ │ ├── Filter.js │ │ │ ├── Gift.js │ │ │ ├── Kebab.js │ │ │ ├── LightColorScheme.js │ │ │ ├── Start.js │ │ │ ├── Bug.js │ │ │ ├── Apple.js │ │ │ ├── DockBottom.js │ │ │ ├── Pictures.js │ │ │ ├── TickAnimation │ │ │ │ ├── styles.css │ │ │ │ └── index.js │ │ │ ├── DarkColorScheme.js │ │ │ ├── Layout.js │ │ │ ├── DockRight.js │ │ │ ├── Proxy.js │ │ │ ├── Zoom.js │ │ │ ├── Twitter.js │ │ │ ├── Muted.js │ │ │ ├── Github.js │ │ │ ├── CrossThin.js │ │ │ ├── ScrollUp.js │ │ │ ├── Cross.js │ │ │ ├── UnDock.js │ │ │ ├── Screenshot.js │ │ │ ├── DoubleLeftArrow.js │ │ │ ├── Minimize.js │ │ │ ├── InspectElement.js │ │ │ ├── DeviceRotate.js │ │ │ ├── InspectElementChrome.js │ │ │ ├── Devices.js │ │ │ └── RoadMap.js │ │ ├── LeftIconsPane │ │ │ └── styles.css │ │ ├── useIsDarkTheme.js │ │ ├── Header │ │ │ └── index.test.js │ │ ├── HorizontalSpacer │ │ │ └── index.js │ │ ├── NotificationMessage │ │ │ └── index.js │ │ ├── PermissionPopup │ │ │ └── styles.module.css │ │ ├── DeviceManager │ │ │ ├── styles.css │ │ │ └── OSIcon.js │ │ ├── ClearNetworkCache │ │ │ └── index.js │ │ ├── StatusBar │ │ │ ├── Announcement.js │ │ │ └── useStyles.js │ │ ├── PrefersColorSchemeSwitch │ │ │ └── index.js │ │ ├── UserPreferences │ │ │ └── useStyles.js │ │ ├── Spinner │ │ │ └── index.js │ │ ├── DevicesPreviewer │ │ │ ├── useStyles.js │ │ │ └── index.test.js │ │ ├── DevicesOverview │ │ │ └── index.js │ │ ├── ScrollControls │ │ │ └── index.test.js │ │ ├── NavigationControls │ │ │ └── index.test.js │ │ ├── AppNotification │ │ │ └── styles.module.css │ │ ├── PreviewerLayoutSelector │ │ │ └── index.js │ │ ├── ZenButton │ │ │ └── index.js │ │ ├── Headway.js │ │ ├── UrlSearchResults │ │ │ └── useStyles.js │ │ ├── Renderer │ │ │ └── index.test.js │ │ ├── WebView │ │ │ └── index.test.js │ │ ├── Select.js │ │ └── useCommonStyles.js │ ├── services │ │ ├── db │ │ │ ├── index.js │ │ │ └── appMetadata.js │ │ └── browserSync │ │ │ └── index.js │ ├── containers │ │ ├── HomePage.js │ │ ├── ZoomContainer │ │ │ └── index.js │ │ ├── HeaderContainer │ │ │ └── index.js │ │ ├── WebViewContainer │ │ │ └── index.js │ │ ├── DrawerContainer │ │ │ └── index.js │ │ ├── AddDeviceContainer │ │ │ └── index.js │ │ ├── DeviceDrawerContainer │ │ │ └── index.js │ │ ├── DeviceManagerContainer │ │ │ └── index.js │ │ ├── DevicePreviewerContainer │ │ │ └── index.js │ │ ├── ScrollControlsContainer │ │ │ └── index.js │ │ ├── DevicesOverviewContainer │ │ │ └── index.js │ │ ├── ExtensionsManagerContainer │ │ │ └── index.js │ │ ├── QuickFilterDevicesContainer │ │ │ └── index.js │ │ ├── LeftIconsPaneContainer │ │ │ └── index.js │ │ ├── UserPreferencesContainer │ │ │ └── index.js │ │ ├── NetworkConfigurationContainer │ │ │ └── index.js │ │ ├── NavigationControlsContainer │ │ │ └── index.js │ │ ├── DevToolResizerContainer │ │ │ └── index.js │ │ ├── StatusBarContainer │ │ │ └── index.js │ │ ├── BookmarksBarContainer │ │ │ └── index.js │ │ └── AddressBar │ │ │ └── index.js │ ├── reducers │ │ ├── index.js │ │ ├── statusBar.js │ │ ├── types.js │ │ └── bookmarks.js │ ├── store │ │ ├── configureStore.js │ │ ├── configureStore.prod.js │ │ └── configureStore.dev.js │ ├── actions │ │ ├── statusBar.js │ │ └── bookmarks.js │ ├── settings │ │ ├── userPreferenceSettings.js │ │ └── statusBarSettings.js │ ├── shortcut-manager │ │ ├── shared.js │ │ ├── renderer-shortcut-manager.js │ │ └── main-shortcut-manager.js │ ├── index.js │ └── imageWorker.js ├── .prettierignore ├── internals │ ├── mocks │ │ └── fileMock.js │ ├── flow │ │ ├── WebpackAsset.js.flow │ │ └── CSSModule.js.flow │ ├── img │ │ ├── js.png │ │ ├── flow.png │ │ ├── jest.png │ │ ├── npm.png │ │ ├── react.png │ │ ├── redux.png │ │ ├── yarn.png │ │ ├── eslint.png │ │ ├── webpack.png │ │ ├── js-padded.png │ │ ├── flow-padded.png │ │ ├── jest-padded.png │ │ ├── react-padded.png │ │ ├── react-router.png │ │ ├── redux-padded.png │ │ ├── yarn-padded.png │ │ ├── eslint-padded.png │ │ ├── flow-padded-90.png │ │ ├── jest-padded-90.png │ │ ├── react-padded-90.png │ │ ├── redux-padded-90.png │ │ ├── webpack-padded.png │ │ ├── yarn-padded-90.png │ │ ├── eslint-padded-90.png │ │ ├── webpack-padded-90.png │ │ ├── react-router-padded.png │ │ └── react-router-padded-90.png │ └── scripts │ │ ├── CheckNodeEnv.js │ │ ├── CheckPortInUse.js │ │ └── CheckBuiltsExist.js ├── .testcafe-electron-rc ├── .stylelintrc ├── flow-typed │ ├── module_vx.x.x.js │ └── electron.js ├── resources │ ├── icon.ico │ ├── icon.png │ ├── icon.icns │ ├── icon.gvdesign │ ├── icon.old.icns │ ├── icon.old.ico │ ├── icon.old.png │ ├── icons │ │ ├── 16x16.png │ │ ├── 32x32.png │ │ ├── 64x64.png │ │ ├── 128x128.png │ │ ├── 256x256.png │ │ ├── 512x512.png │ │ └── 1024x1024.png │ ├── icons.old │ │ ├── 16x16.png │ │ ├── 32x32.png │ │ ├── 64x64.png │ │ ├── 1024x1024.png │ │ ├── 128x128.png │ │ ├── 256x256.png │ │ ├── 512x512.png │ │ ├── icon16x16.png │ │ ├── icon32x32.png │ │ ├── icon64x64.png │ │ ├── icon128x128.png │ │ ├── icon256x256.png │ │ ├── icon512x512.png │ │ └── icon1024x1024.png │ ├── logo_with_padding.png │ ├── responsively-logo.png │ ├── redo.svg │ ├── arrow-left.svg │ ├── cross.svg │ ├── arrow-right.svg │ ├── code.svg │ ├── camera-plus.svg │ ├── apple.svg │ ├── dock-bottom.svg │ ├── bug.svg │ ├── dock-right.svg │ ├── scenery.svg │ ├── undock.svg │ ├── inspect-element-chrome.svg │ ├── inspect-element.svg │ ├── cross-thin.svg │ ├── focus.svg │ ├── unfocus.svg │ ├── logo.old.svg │ └── home.svg ├── .gitattributes ├── scripts │ ├── chocolatey │ │ └── responsively │ │ │ └── tools │ │ │ ├── VERIFICATION.txt │ │ │ ├── chocolateyinstall.ps1 │ │ │ └── chocolateyuninstall.ps1 │ ├── extraPublishFiles.js │ └── notarize.js ├── renovate.json ├── configs │ ├── webpack.config.eslint.js │ ├── webpack.config.base.js │ └── webpack.config.renderer.dev.dll.babel.js ├── .editorconfig ├── .prettierrc ├── build │ └── entitlements.mac.plist ├── appveyor.yml ├── .github │ ├── stale.yml │ └── ISSUE_TEMPLATE.md ├── add-osx-cert.sh ├── .vscode │ └── settings.json ├── .flowconfig ├── .dockerignore ├── .eslintignore ├── .gitignore └── LICENSE ├── .github ├── opencollective.yml ├── ISSUE_TEMPLATE │ ├── 02-feature-request.md │ └── 01-bug-report.md ├── workflows │ └── lint.yml ├── FUNDING.yml └── PULL_REQUEST_TEMPLATE.md ├── browser-extension ├── .gitignore ├── public │ ├── logo_128.png │ ├── logo_16.png │ ├── logo_48.png │ ├── manifest.json │ └── popup.html ├── .vscode │ └── settings.json ├── src │ └── background.js ├── webpack.config.js └── package.json ├── .gitattributes ├── .travis.yml ├── .gitlab-ci.yml └── dev.code-workspace /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /desktop-app/.nvmrc: -------------------------------------------------------------------------------- 1 | 12.13.0 2 | -------------------------------------------------------------------------------- /desktop-app/app/utils/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/opencollective.yml: -------------------------------------------------------------------------------- 1 | collective: responsively 2 | -------------------------------------------------------------------------------- /desktop-app/.prettierignore: -------------------------------------------------------------------------------- 1 | build/entitlements.mac.plist 2 | -------------------------------------------------------------------------------- /desktop-app/internals/mocks/fileMock.js: -------------------------------------------------------------------------------- 1 | export default 'test-file-stub'; 2 | -------------------------------------------------------------------------------- /desktop-app/internals/flow/WebpackAsset.js.flow: -------------------------------------------------------------------------------- 1 | // @flow 2 | declare export default string 3 | -------------------------------------------------------------------------------- /browser-extension/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | dist 4 | setCreds.sh 5 | web-ext-artifacts 6 | -------------------------------------------------------------------------------- /desktop-app/.testcafe-electron-rc: -------------------------------------------------------------------------------- 1 | { 2 | "mainWindowUrl": "./app/app.html", 3 | "appPath": "." 4 | } 5 | -------------------------------------------------------------------------------- /desktop-app/app/constants/routes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | HOME: '/', 3 | COUNTER: '/counter', 4 | }; 5 | -------------------------------------------------------------------------------- /desktop-app/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard", "stylelint-config-prettier"] 3 | } 4 | -------------------------------------------------------------------------------- /desktop-app/app/constants/searchResultSettings.js: -------------------------------------------------------------------------------- 1 | export const ADD_SEARCH_RESULTS = 'ADD_SEARCH_RESULTS'; 2 | -------------------------------------------------------------------------------- /desktop-app/app/constants/theme.js: -------------------------------------------------------------------------------- 1 | export const LIGHT_THEME = 'light'; 2 | export const DARK_THEME = 'dark'; 3 | -------------------------------------------------------------------------------- /desktop-app/flow-typed/module_vx.x.x.js: -------------------------------------------------------------------------------- 1 | declare module 'module' { 2 | declare module.exports: any; 3 | } 4 | -------------------------------------------------------------------------------- /desktop-app/internals/flow/CSSModule.js.flow: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare export default { [key: string]: string } -------------------------------------------------------------------------------- /desktop-app/app/app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/app/app.icns -------------------------------------------------------------------------------- /desktop-app/app/components/DeviceDrawer/styles.css: -------------------------------------------------------------------------------- 1 | .label { 2 | font-size: 14px; 3 | margin-bottom: 5px; 4 | } 5 | -------------------------------------------------------------------------------- /desktop-app/app/constants/license.js: -------------------------------------------------------------------------------- 1 | export const DEACTIVATION_REASON = { 2 | REVALIDATION: 'REVALIDATION', 3 | }; 4 | -------------------------------------------------------------------------------- /desktop-app/app/components/NetworkConfiguration/styles.css: -------------------------------------------------------------------------------- 1 | .label { 2 | font-size: 14px; 3 | margin-bottom: 5px; 4 | } 5 | -------------------------------------------------------------------------------- /desktop-app/app/services/db/index.js: -------------------------------------------------------------------------------- 1 | import appMetadataDB from './appMetadata'; 2 | 3 | export default {appMetadataDB}; 4 | -------------------------------------------------------------------------------- /desktop-app/resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.ico -------------------------------------------------------------------------------- /desktop-app/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.png -------------------------------------------------------------------------------- /desktop-app/.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.png binary 3 | *.jpg binary 4 | *.jpeg binary 5 | *.ico binary 6 | *.icns binary 7 | -------------------------------------------------------------------------------- /desktop-app/internals/img/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/js.png -------------------------------------------------------------------------------- /desktop-app/resources/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.icns -------------------------------------------------------------------------------- /desktop-app/app/constants/browserSync.js: -------------------------------------------------------------------------------- 1 | export const BROWSER_SYNC_VERSION = '2.26.7'; 2 | export const BROWSER_SYNC_PORT = '12719'; 3 | -------------------------------------------------------------------------------- /desktop-app/internals/img/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/flow.png -------------------------------------------------------------------------------- /desktop-app/internals/img/jest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/jest.png -------------------------------------------------------------------------------- /desktop-app/internals/img/npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/npm.png -------------------------------------------------------------------------------- /desktop-app/internals/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/react.png -------------------------------------------------------------------------------- /desktop-app/internals/img/redux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/redux.png -------------------------------------------------------------------------------- /desktop-app/internals/img/yarn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/yarn.png -------------------------------------------------------------------------------- /desktop-app/resources/icon.gvdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.gvdesign -------------------------------------------------------------------------------- /desktop-app/resources/icon.old.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.old.icns -------------------------------------------------------------------------------- /desktop-app/resources/icon.old.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.old.ico -------------------------------------------------------------------------------- /desktop-app/resources/icon.old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icon.old.png -------------------------------------------------------------------------------- /browser-extension/public/logo_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/browser-extension/public/logo_128.png -------------------------------------------------------------------------------- /browser-extension/public/logo_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/browser-extension/public/logo_16.png -------------------------------------------------------------------------------- /browser-extension/public/logo_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/browser-extension/public/logo_48.png -------------------------------------------------------------------------------- /desktop-app/internals/img/eslint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/eslint.png -------------------------------------------------------------------------------- /desktop-app/internals/img/webpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/webpack.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/16x16.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/32x32.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/64x64.png -------------------------------------------------------------------------------- /browser-extension/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.defaultFormatter": "esbenp.prettier-vscode" 4 | } 5 | -------------------------------------------------------------------------------- /desktop-app/app/components/ZoomInput/otherStyles.css: -------------------------------------------------------------------------------- 1 | .MuiSlider-markLabelActive, 2 | .MuiSlider-markLabel { 3 | color: white !important; 4 | } 5 | -------------------------------------------------------------------------------- /desktop-app/internals/img/js-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/js-padded.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/128x128.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/256x256.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/512x512.png -------------------------------------------------------------------------------- /desktop-app/app/utils/stringUtils.js: -------------------------------------------------------------------------------- 1 | export function isNullOrWhiteSpaces(str: string): boolean { 2 | return str == null || /^\s*$/.test(str); 3 | } 4 | -------------------------------------------------------------------------------- /desktop-app/internals/img/flow-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/flow-padded.png -------------------------------------------------------------------------------- /desktop-app/internals/img/jest-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/jest-padded.png -------------------------------------------------------------------------------- /desktop-app/internals/img/react-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/react-padded.png -------------------------------------------------------------------------------- /desktop-app/internals/img/react-router.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/react-router.png -------------------------------------------------------------------------------- /desktop-app/internals/img/redux-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/redux-padded.png -------------------------------------------------------------------------------- /desktop-app/internals/img/yarn-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/yarn-padded.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/16x16.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/32x32.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/64x64.png -------------------------------------------------------------------------------- /desktop-app/resources/icons/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons/1024x1024.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.css linguist-detectable=false 2 | *.html linguist-detectable=false 3 | *.htm linguist-detectable=false 4 | *.js linguist-detectable=true 5 | -------------------------------------------------------------------------------- /desktop-app/internals/img/eslint-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/eslint-padded.png -------------------------------------------------------------------------------- /desktop-app/internals/img/flow-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/flow-padded-90.png -------------------------------------------------------------------------------- /desktop-app/internals/img/jest-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/jest-padded-90.png -------------------------------------------------------------------------------- /desktop-app/internals/img/react-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/react-padded-90.png -------------------------------------------------------------------------------- /desktop-app/internals/img/redux-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/redux-padded-90.png -------------------------------------------------------------------------------- /desktop-app/internals/img/webpack-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/webpack-padded.png -------------------------------------------------------------------------------- /desktop-app/internals/img/yarn-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/yarn-padded-90.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/1024x1024.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/128x128.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/256x256.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/512x512.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon16x16.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon32x32.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon64x64.png -------------------------------------------------------------------------------- /desktop-app/resources/logo_with_padding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/logo_with_padding.png -------------------------------------------------------------------------------- /desktop-app/resources/responsively-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/responsively-logo.png -------------------------------------------------------------------------------- /desktop-app/internals/img/eslint-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/eslint-padded-90.png -------------------------------------------------------------------------------- /desktop-app/internals/img/webpack-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/webpack-padded-90.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon128x128.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon256x256.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon512x512.png -------------------------------------------------------------------------------- /desktop-app/app/components/ScreenshotManager/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function Screenshotmanager(props) { 4 | return ''; 5 | } 6 | -------------------------------------------------------------------------------- /desktop-app/internals/img/react-router-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/react-router-padded.png -------------------------------------------------------------------------------- /desktop-app/resources/icons.old/icon1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/resources/icons.old/icon1024x1024.png -------------------------------------------------------------------------------- /desktop-app/internals/img/react-router-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/internals/img/react-router-padded-90.png -------------------------------------------------------------------------------- /browser-extension/src/background.js: -------------------------------------------------------------------------------- 1 | browser.browserAction.onClicked.addListener((tab) => { 2 | browser.tabs.executeScript({ 3 | file: './openURL.js' 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /desktop-app/app/components/NetworkThrottling/styles.css: -------------------------------------------------------------------------------- 1 | .networkThrottlingIcon { 2 | margin-right: 5px; 3 | } 4 | .throttlingProfileSelectorContainer { 5 | margin-bottom: 20px; 6 | } 7 | -------------------------------------------------------------------------------- /desktop-app/app/components/ExtensionsManager/help-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidthesloth92/responsively-app/master/desktop-app/app/components/ExtensionsManager/help-screenshot.png -------------------------------------------------------------------------------- /desktop-app/app/components/ZoomInput/styles.module.css: -------------------------------------------------------------------------------- 1 | .zoomControls { 2 | position: absolute; 3 | right: 0; 4 | } 5 | 6 | .label { 7 | font-size: 1rem; 8 | margin-right: 1rem; 9 | } 10 | -------------------------------------------------------------------------------- /desktop-app/app/constants/values.js: -------------------------------------------------------------------------------- 1 | export const SCREENSHOT_MECHANISM = { 2 | V1: 'V1', 3 | V2: 'V2', 4 | }; 5 | 6 | export const SSL_ERROR_CODES = { 7 | FIRST: -200, 8 | LAST: -299, 9 | }; 10 | -------------------------------------------------------------------------------- /desktop-app/scripts/chocolatey/responsively/tools/VERIFICATION.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VERIFICATION 5 | I'm the author 6 | 7 | powershell > (Get-FileHash -Path .\ResponsivelyApp-Setup-#VERSION#.exe -Algorithm 'sha512').Hash -------------------------------------------------------------------------------- /desktop-app/app/utils/urlUtils.js: -------------------------------------------------------------------------------- 1 | export function getHostFromURL(url: String) { 2 | let host = ''; 3 | if (url) { 4 | const urlObj = new URL(url); 5 | host = urlObj.host; 6 | } 7 | return host; 8 | } 9 | -------------------------------------------------------------------------------- /desktop-app/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "rangeStrategy": "bump", 4 | "baseBranches": ["next"], 5 | "automerge": true, 6 | "major": { 7 | "automerge": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /desktop-app/configs/webpack.config.eslint.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-unresolved: off, import/no-self-import: off */ 2 | require('@babel/register'); 3 | 4 | module.exports = require('./webpack.config.renderer.dev.babel').default; 5 | -------------------------------------------------------------------------------- /desktop-app/resources/redo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 12.13.0 4 | os: osx 5 | osx_image: xcode10.2 6 | before_install: cd desktop-app 7 | install: 8 | - brew install yarn 9 | - yarn 10 | - sh add-osx-cert.sh 11 | script: 12 | - yarn run package-mac 13 | -------------------------------------------------------------------------------- /desktop-app/app/utils/logUtils.js: -------------------------------------------------------------------------------- 1 | import * as Sentry from '@sentry/electron'; 2 | 3 | export const captureOnSentry = err => { 4 | console.log('err', err); 5 | if (process.env.NODE_ENV !== 'development') { 6 | Sentry.captureException(err); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /desktop-app/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /desktop-app/flow-typed/electron.js: -------------------------------------------------------------------------------- 1 | declare class WebviewElement extends HTMLElement { 2 | insertCSS: string => Promise, 3 | executeJavaScript: string => Promise, 4 | getWebContentsId: () => number, 5 | removeInsertedCSS: number => Promise, 6 | } 7 | -------------------------------------------------------------------------------- /desktop-app/resources/arrow-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/resources/cross.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/resources/arrow-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/constants/permissionsManagement.js: -------------------------------------------------------------------------------- 1 | const PERMISSION_MANAGEMENT_OPTIONS = { 2 | ALLOW_ALWAYS: 'Allow always', 3 | DENY_ALWAYS: 'Deny always', 4 | ASK_ALWAYS: 'Ask always', 5 | }; 6 | 7 | Object.freeze(PERMISSION_MANAGEMENT_OPTIONS); 8 | 9 | export {PERMISSION_MANAGEMENT_OPTIONS}; 10 | -------------------------------------------------------------------------------- /desktop-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": [".prettierrc", ".babelrc", ".eslintrc", ".stylelintrc"], 5 | "options": { 6 | "parser": "json" 7 | } 8 | } 9 | ], 10 | "singleQuote": true, 11 | "bracketSpacing": false, 12 | "trailingComma": "es5" 13 | } 14 | -------------------------------------------------------------------------------- /desktop-app/app/constants/previewerLayouts.js: -------------------------------------------------------------------------------- 1 | export const HORIZONTAL_LAYOUT = 'HORIZONTAL'; 2 | export const FLEXIGRID_LAYOUT = 'FLEXIGRID'; 3 | export const INDIVIDUAL_LAYOUT = 'INDIVIDUAL'; 4 | 5 | export const DEVTOOLS_MODES = { 6 | BOTTOM: 'BOTTOM', 7 | RIGHT: 'RIGHT', 8 | UNDOCKED: 'UNDOCKED', 9 | }; 10 | -------------------------------------------------------------------------------- /desktop-app/app/containers/HomePage.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, {Component} from 'react'; 3 | import Home from '../components/Home'; 4 | 5 | type Props = {}; 6 | 7 | export default class HomePage extends Component { 8 | props: Props; 9 | 10 | render() { 11 | return ; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /desktop-app/app/constants/DrawerContents.js: -------------------------------------------------------------------------------- 1 | export const DEVICE_MANAGER = 'DEVICE_MANAGER'; 2 | export const SCREENSHOT_MANAGER = 'SCREENSHOT_MANAGER'; 3 | export const USER_PREFERENCES = 'USER_PREFERENCES'; 4 | export const EXTENSIONS_MANAGER = 'EXTENSIONS_MANAGER'; 5 | export const NETWORK_CONFIGURATION = 'NETWORK_CONFIGURATION'; 6 | -------------------------------------------------------------------------------- /desktop-app/build/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-unsigned-executable-memory 6 | 7 | 8 | -------------------------------------------------------------------------------- /desktop-app/resources/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/styles.module.css: -------------------------------------------------------------------------------- 1 | .chromeIcon { 2 | fill: rgb(165, 165, 165); 3 | margin-right: 5px; 4 | height: 12px; 5 | cursor: pointer; 6 | } 7 | 8 | .chromeIcon.selected { 9 | fill: #7587ec; 10 | } 11 | 12 | @media (prefers-color-scheme: light) { 13 | .chromeIcon { 14 | fill: #555; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: electronuserland/builder:wine 2 | 3 | before_script: 4 | - apt-get update 5 | - apt-get install --no-install-recommends -y libopenjp2-tools 6 | - cd desktop-app 7 | 8 | stages: 9 | - buildPublish 10 | 11 | build_and_publish: 12 | stage: buildPublish 13 | script: 14 | - yarn 15 | - yarn run package-ci 16 | 17 | -------------------------------------------------------------------------------- /desktop-app/app/components/LeftIconsPane/styles.css: -------------------------------------------------------------------------------- 1 | .icon { 2 | margin-bottom: 10px !important; 3 | } 4 | 5 | .utilitySection { 6 | flex: 1; 7 | margin-top: 50px !important; 8 | } 9 | 10 | .logo { 11 | background: white; 12 | border-radius: 9%; 13 | margin-bottom: 50px; 14 | display: flex; 15 | justify-content: center; 16 | margin: 3px; 17 | } 18 | -------------------------------------------------------------------------------- /desktop-app/app/reducers/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import {combineReducers} from 'redux'; 3 | import browser from './browser'; 4 | import bookmarks from './bookmarks'; 5 | import statusBar from './statusBar'; 6 | 7 | export default function createRootReducer() { 8 | return combineReducers({ 9 | browser, 10 | bookmarks, 11 | statusBar, 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /desktop-app/app/store/configureStore.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import configureStoreDev from './configureStore.dev'; 3 | import configureStoreProd from './configureStore.prod'; 4 | 5 | const selectedConfigureStore = 6 | process.env.NODE_ENV === 'production' 7 | ? configureStoreProd 8 | : configureStoreDev; 9 | 10 | export const {configureStore} = selectedConfigureStore; 11 | -------------------------------------------------------------------------------- /desktop-app/app/constants/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | /** 4 | * Default zoom level for the application. 5 | */ 6 | export const DEFAULT_ZOOM_LEVEL = 0.6; 7 | 8 | /** 9 | * Minimum zoom threshold for the application. 10 | */ 11 | export const MIN_ZOOM_LEVEL = 0.2; 12 | 13 | /** 14 | * Maximum zoom threshold for the application. 15 | */ 16 | export const MAX_ZOOM_LEVEL = 2.0; 17 | -------------------------------------------------------------------------------- /desktop-app/app/constants/settingKeys.js: -------------------------------------------------------------------------------- 1 | export const ACTIVE_DEVICES = 'activeDevices'; 2 | export const CUSTOM_DEVICES = 'customDevices'; 3 | export const USER_PREFERENCES = 'userPreferences'; 4 | export const NETWORK_CONFIGURATION = 'networkConfiguration'; 5 | export const BOOKMARKS = 'bookmarks'; 6 | export const STATUS_BAR_VISIBILITY = 'statusBarVisibility'; 7 | export const APP_NOTIFICATION = 'appNotification'; 8 | -------------------------------------------------------------------------------- /desktop-app/app/services/db/appMetadata.js: -------------------------------------------------------------------------------- 1 | const db = require('electron-settings'); 2 | 3 | const OPEN_COUNT = 'openCount'; 4 | 5 | class AppMetadata { 6 | incrementOpenCount() { 7 | const count = db.get(OPEN_COUNT) || 0; 8 | db.set(OPEN_COUNT, count + 1); 9 | } 10 | 11 | getOpenCount() { 12 | return db.get(OPEN_COUNT) || 0; 13 | } 14 | } 15 | 16 | export default new AppMetadata(); 17 | -------------------------------------------------------------------------------- /desktop-app/app/components/useIsDarkTheme.js: -------------------------------------------------------------------------------- 1 | import useMediaQuery from '@material-ui/core/useMediaQuery'; 2 | import {useSelector} from 'react-redux'; 3 | import {LIGHT_THEME, DARK_THEME} from '../constants/theme'; 4 | import {setTheme} from '../actions/browser'; 5 | 6 | function useIsDarkTheme() { 7 | const themeSource = useSelector(state => state.browser.theme); 8 | return themeSource === DARK_THEME; 9 | } 10 | 11 | export default useIsDarkTheme; 12 | -------------------------------------------------------------------------------- /desktop-app/app/components/Header/index.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {shallow} from 'enzyme'; 3 | import {expect} from 'chai'; 4 | 5 | import Header from '.'; 6 | 7 | describe('
', () => { 8 | it('renders a h1 and BrowserZoom components', () => { 9 | const wrapper = shallow(
); 10 | expect(wrapper.find('h1')).to.have.lengthOf(1); 11 | expect(wrapper.find('ZoomInput')).to.have.lengthOf(1); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /desktop-app/scripts/extraPublishFiles.js: -------------------------------------------------------------------------------- 1 | const {generateChecksums} = require('./generate-checksums'); 2 | const {version, build, productName} = require('../package.json'); 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | 6 | const getExtraPublishFiles = () => 7 | generateChecksums().then(files => { 8 | console.log(`\nExtra Files Included:\n${files.join('\n')}`); 9 | return files; 10 | }); 11 | 12 | exports.default = getExtraPublishFiles; 13 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Logo.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import logoImage from '../../../resources/logo.svg'; 4 | 5 | export default function Logo({ 6 | width, 7 | height, 8 | color, 9 | padding, 10 | margin, 11 | className, 12 | }) { 13 | return ( 14 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /desktop-app/app/actions/statusBar.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import {statusBarSettings} from '../settings/statusBarSettings'; 3 | 4 | export const TOGGLE_STATUS_BAR_VISIBILITY = 'TOGGLE_STATUS_BAR_VISIBILITY'; 5 | 6 | export function toggleStatusBarVisibility() { 7 | const newVisibility = !statusBarSettings.getVisibility(); 8 | statusBarSettings.setVisibility(newVisibility); 9 | 10 | return { 11 | type: TOGGLE_STATUS_BAR_VISIBILITY, 12 | visible: newVisibility, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /desktop-app/resources/camera-plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/resources/apple.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/internals/scripts/CheckNodeEnv.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import chalk from 'chalk'; 3 | 4 | export default function CheckNodeEnv(expectedEnv: string) { 5 | if (!expectedEnv) { 6 | throw new Error('"expectedEnv" not set'); 7 | } 8 | 9 | if (process.env.NODE_ENV !== expectedEnv) { 10 | console.log( 11 | chalk.whiteBright.bgRed.bold( 12 | `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config` 13 | ) 14 | ); 15 | process.exit(2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /desktop-app/app/services/browserSync/index.js: -------------------------------------------------------------------------------- 1 | import {ipcRenderer} from 'electron'; 2 | import browserSync from 'browser-sync'; 3 | 4 | let browserSyncOptions; 5 | 6 | initializeBrowserSyncOptions(); 7 | 8 | async function initializeBrowserSyncOptions() { 9 | if (!browserSyncOptions) { 10 | browserSyncOptions = await ipcRenderer.invoke('request-browser-sync'); 11 | } 12 | } 13 | 14 | export function getBrowserSyncEmbedScriptURL() { 15 | if (browserSyncOptions) { 16 | return browserSyncOptions.url; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/02-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature request" 3 | about: Suggest a feature for Responsively. 4 | --- 5 | 6 | # 🚀 Feature Request 7 | 8 | ### 📝 Description 9 | 10 | 11 | 12 | ### ✨ Describe the solution you'd like 13 | 14 | 15 | 16 | ### ✍️ Describe alternatives you've considered 17 | 18 | 19 | -------------------------------------------------------------------------------- /desktop-app/app/actions/bookmarks.js: -------------------------------------------------------------------------------- 1 | export const TOGGLE_BOOKMARK = 'TOGGLE_BOOKMARK'; 2 | export const EDIT_BOOKMARK = 'EDIT_BOOKMARK'; 3 | 4 | // Add or Remove an URL from the bookmark list 5 | export function toggleBookmarkUrl(url, pageMeta = {}) { 6 | return { 7 | type: TOGGLE_BOOKMARK, 8 | url, 9 | title: pageMeta.title, 10 | }; 11 | } 12 | 13 | // Updates bookmark title 14 | export function editBookmark(bookmark, {title, url}) { 15 | return { 16 | type: EDIT_BOOKMARK, 17 | title, 18 | url, 19 | bookmark, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Chevron.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | /** 4 | * Flattened Chevron icon. 5 | */ 6 | export default ({width, height, color, padding, margin}) => ( 7 | 15 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /desktop-app/app/utils/browserUtils.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import {MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL} from '../constants'; 4 | 5 | /** 6 | * Ensures that the given zoom level stays between MIN_ZOOM_LEVEL and MAX_ZOOM_LEVEL and returns it. 7 | * @param zoomLevel The zoom level to be normalized. 8 | */ 9 | export function normalizeZoomLevel(zoomLevel: number): number { 10 | if (zoomLevel < MIN_ZOOM_LEVEL) { 11 | return MIN_ZOOM_LEVEL; 12 | } 13 | 14 | if (zoomLevel > MAX_ZOOM_LEVEL) { 15 | return MAX_ZOOM_LEVEL; 16 | } 17 | 18 | return zoomLevel; 19 | } 20 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Reload.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /desktop-app/app/components/HorizontalSpacer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {makeStyles} from '@material-ui/core/styles'; 3 | 4 | /** 5 | * Application toolbar that appears at the top of a window. 6 | */ 7 | const HorizontalSpacer = () => { 8 | const classes = useStyles(); 9 | return
; 10 | }; 11 | 12 | const useStyles = makeStyles(theme => ({ 13 | container: { 14 | background: theme.palette.background.l1, 15 | padding: '11px 0', 16 | zIndex: '10', 17 | }, 18 | })); 19 | 20 | export default HorizontalSpacer; 21 | -------------------------------------------------------------------------------- /desktop-app/app/containers/ZoomContainer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from 'react-redux'; 3 | import {bindActionCreators} from 'redux'; 4 | 5 | import ZoomInput from '../../components/ZoomInput'; 6 | import * as BrowserActions from '../../actions/browser'; 7 | 8 | function mapStateToProps(state) { 9 | return { 10 | browser: state.browser, 11 | }; 12 | } 13 | 14 | function mapDispatchToProps(dispatch) { 15 | return bindActionCreators(BrowserActions, dispatch); 16 | } 17 | 18 | export default connect(mapStateToProps, mapDispatchToProps)(ZoomInput); 19 | -------------------------------------------------------------------------------- /desktop-app/app/containers/HeaderContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import Header from '../../components/Header'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | isHeaderVisible: state.browser.isHeaderVisible, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(Header); 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/WebViewContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {bindActionCreators} from 'redux'; 4 | import {connect} from 'react-redux'; 5 | import WebView from '../../components/WebView'; 6 | import * as BrowserActions from '../../actions/browser'; 7 | 8 | function mapStateToProps(state) { 9 | return { 10 | browser: state.browser, 11 | }; 12 | } 13 | 14 | function mapDispatchToProps(dispatch) { 15 | return bindActionCreators(BrowserActions, dispatch); 16 | } 17 | 18 | export default connect(mapStateToProps, mapDispatchToProps)(WebView); 19 | -------------------------------------------------------------------------------- /desktop-app/app/components/NotificationMessage/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Spinner from '../Spinner'; 3 | import Tick from '../icons/TickAnimation'; 4 | 5 | export default function NotificationMessage(props) { 6 | return ( 7 |
8 | {props.spinner && ( 9 |
10 | 11 |
12 | )} 13 | {props.tick && ( 14 |
15 | 16 |
17 | )} 18 | {props.message} 19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /desktop-app/app/containers/DrawerContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import Drawer from '../../components/Drawer'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | drawer: state.browser.drawer, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(Drawer); 20 | -------------------------------------------------------------------------------- /desktop-app/scripts/notarize.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const {notarize} = require('electron-notarize'); 3 | 4 | exports.default = async function notarizing(context) { 5 | const {electronPlatformName, appOutDir} = context; 6 | if (electronPlatformName !== 'darwin') { 7 | return; 8 | } 9 | 10 | const appName = context.packager.appInfo.productFilename; 11 | 12 | return notarize({ 13 | appBundleId: 'app.responsively', 14 | appPath: `${appOutDir}/${appName}.app`, 15 | appleId: process.env.APPLEID, 16 | appleIdPassword: process.env.APPLEIDPASS, 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /dev.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "desktop-app" 5 | }, 6 | { 7 | "path": "browser-extension" 8 | } 9 | ], 10 | "settings": { 11 | "files.associations": { 12 | ".babelrc": "jsonc", 13 | ".eslintrc": "jsonc", 14 | ".prettierrc": "jsonc", 15 | ".stylelintrc": "json", 16 | ".dockerignore": "ignore", 17 | ".eslintignore": "ignore", 18 | ".flowconfig": "ignore" 19 | }, 20 | "javascript.validate.enable": false, 21 | "javascript.format.enable": false, 22 | "typescript.validate.enable": false, 23 | "typescript.format.enable": false 24 | } 25 | } -------------------------------------------------------------------------------- /desktop-app/app/reducers/statusBar.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import {TOGGLE_STATUS_BAR_VISIBILITY} from '../actions/statusBar'; 3 | import {statusBarSettings} from '../settings/statusBarSettings'; 4 | 5 | export type StatusBarStateType = {visible: boolean}; 6 | 7 | export default function app( 8 | state: StatusBarStateType = {visible: statusBarSettings.getVisibility()}, 9 | action: Action 10 | ) { 11 | switch (action.type) { 12 | case TOGGLE_STATUS_BAR_VISIBILITY: 13 | return { 14 | ...state, 15 | visible: action.visible, 16 | }; 17 | default: 18 | return state; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /desktop-app/resources/dock-bottom.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/containers/AddDeviceContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import AddDevice from '../../components/DeviceManager/AddDevice'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(AddDevice); 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/DeviceDrawerContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import DeviceDrawer from '../../components/DeviceDrawer'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(DeviceDrawer); 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/DeviceManagerContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import DeviceManager from '../../components/DeviceManager'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(DeviceManager); 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/DevicePreviewerContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {bindActionCreators} from 'redux'; 4 | import {connect} from 'react-redux'; 5 | import DevicesPreviewer from '../../components/DevicesPreviewer'; 6 | import * as BrowserActions from '../../actions/browser'; 7 | 8 | function mapStateToProps(state) { 9 | return { 10 | browser: state.browser, 11 | }; 12 | } 13 | 14 | function mapDispatchToProps(dispatch) { 15 | return bindActionCreators(BrowserActions, dispatch); 16 | } 17 | 18 | export default connect(mapStateToProps, mapDispatchToProps)(DevicesPreviewer); 19 | -------------------------------------------------------------------------------- /desktop-app/app/containers/ScrollControlsContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import ScrollControls from '../../components/ScrollControls'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(ScrollControls); 20 | -------------------------------------------------------------------------------- /desktop-app/app/reducers/types.js: -------------------------------------------------------------------------------- 1 | import type {Dispatch as ReduxDispatch, Store as ReduxStore} from 'redux'; 2 | import type {BrowserStateType as _BrowserStateType} from './browser'; 3 | 4 | export type BrowserStateType = _BrowserStateType; 5 | 6 | export type counterStateType = { 7 | +counter: number, 8 | }; 9 | 10 | export type RootStateType = { 11 | browser: BrowserStateType, 12 | }; 13 | 14 | export type Action = { 15 | +type: string, 16 | }; 17 | 18 | export type GetState = () => RootStateType; 19 | 20 | export type Dispatch = ReduxDispatch; 21 | 22 | export type Store = ReduxStore; 23 | -------------------------------------------------------------------------------- /desktop-app/internals/scripts/CheckPortInUse.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import chalk from 'chalk'; 3 | import detectPort from 'detect-port'; 4 | 5 | (function CheckPortInUse() { 6 | const port: string = process.env.PORT || '1212'; 7 | 8 | detectPort(port, (err: ?Error, availablePort: number) => { 9 | if (port !== String(availablePort)) { 10 | throw new Error( 11 | chalk.whiteBright.bgRed.bold( 12 | `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 yarn dev` 13 | ) 14 | ); 15 | } else { 16 | process.exit(0); 17 | } 18 | }); 19 | })(); 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/DevicesOverviewContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import DevicesOverview from '../../components/DevicesOverview'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(DevicesOverview); 20 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/ArrowLeft.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /desktop-app/app/settings/userPreferenceSettings.js: -------------------------------------------------------------------------------- 1 | import settings from 'electron-settings'; 2 | import {USER_PREFERENCES} from '../constants/settingKeys'; 3 | import * as os from 'os'; 4 | 5 | const path = require('path'); 6 | 7 | class UserPreferenceSettings { 8 | getScreenShotSavePath = () => 9 | (settings.get(USER_PREFERENCES) || {}).screenShotSavePath; 10 | getDefaultScreenshotpath = () => 11 | path.join(os.homedir(), `Desktop/Responsively-Screenshots`); 12 | } 13 | 14 | const userPreferenceSettingsInstance = new UserPreferenceSettings(); 15 | 16 | export {userPreferenceSettingsInstance as userPreferenceSettings}; 17 | -------------------------------------------------------------------------------- /desktop-app/app/utils/filterUtils.js: -------------------------------------------------------------------------------- 1 | import {FILTER_FIELDS} from '../reducers/browser'; 2 | 3 | export const isDeviceEligible = (device, filterCriteria) => { 4 | if (Object.keys(filterCriteria[FILTER_FIELDS.OS]).length > 0) { 5 | if (filterCriteria[FILTER_FIELDS.OS].indexOf(device.os) === -1) { 6 | return false; 7 | } 8 | } 9 | 10 | if (Object.keys(filterCriteria[FILTER_FIELDS.DEVICE_TYPE]).length > 0) { 11 | if (filterCriteria[FILTER_FIELDS.DEVICE_TYPE].indexOf(device.type) === -1) { 12 | return false; 13 | } 14 | } 15 | 16 | return true; 17 | }; 18 | 19 | export default {isDeviceEligible}; 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/ExtensionsManagerContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import ExtensionsManager from '../../components/ExtensionsManager'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(ExtensionsManager); 20 | -------------------------------------------------------------------------------- /desktop-app/app/containers/QuickFilterDevicesContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import QuickFilterDevices from '../../components/QuickFilterDevices'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | browser: state.browser, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(QuickFilterDevices); 20 | -------------------------------------------------------------------------------- /desktop-app/app/utils/navigatorUtils.js: -------------------------------------------------------------------------------- 1 | import settings from 'electron-settings'; 2 | import path from 'path'; 3 | 4 | const HOME_PAGE = 'HOME_PAGE'; 5 | const LAST_OPENED_ADDRESS = 'LAST_OPENED_ADDRESS'; 6 | 7 | export function saveHomepage(url) { 8 | settings.set(HOME_PAGE, url); 9 | } 10 | 11 | export function saveLastOpenedAddress(url) { 12 | settings.set(LAST_OPENED_ADDRESS, url); 13 | } 14 | 15 | export function getHomepage() { 16 | return settings.get(HOME_PAGE) || 'https://www.google.com/'; 17 | } 18 | 19 | export function getLastOpenedAddress() { 20 | return settings.get(LAST_OPENED_ADDRESS) || getHomepage(); 21 | } 22 | -------------------------------------------------------------------------------- /desktop-app/resources/bug.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/ArrowRight.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /desktop-app/app/containers/LeftIconsPaneContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import {connect} from 'react-redux'; 3 | import {bindActionCreators} from 'redux'; 4 | 5 | import LeftIconsPane from '../../components/LeftIconsPane'; 6 | import * as BrowserActions from '../../actions/browser'; 7 | 8 | function mapStateToProps(state) { 9 | return { 10 | drawer: state.browser.drawer, 11 | isLeftPaneVisible: state.browser.isLeftPaneVisible, 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators(BrowserActions, dispatch); 17 | } 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(LeftIconsPane); 20 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Windows.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /desktop-app/appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2017 2 | 3 | platform: 4 | - x64 5 | 6 | environment: 7 | matrix: 8 | - nodejs_version: 10 9 | 10 | cache: 11 | - '%LOCALAPPDATA%/Yarn' 12 | - node_modules 13 | - flow-typed 14 | - '%USERPROFILE%\.electron' 15 | 16 | matrix: 17 | fast_finish: true 18 | 19 | build: off 20 | 21 | version: '{build}' 22 | 23 | shallow_clone: true 24 | 25 | clone_depth: 1 26 | 27 | install: 28 | - ps: Install-Product node $env:nodejs_version x64 29 | - set CI=true 30 | - yarn 31 | 32 | test_script: 33 | - yarn package-ci 34 | - yarn lint 35 | # - yarn flow 36 | - yarn test 37 | - yarn build-e2e 38 | - yarn test-e2e 39 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | eslint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: hallee/eslint-action@1.0.3 11 | # GITHUB_TOKEN in forked repositories is read-only 12 | # https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request 13 | if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }} 14 | with: 15 | repo-token: ${{secrets.GITHUB_TOKEN}} 16 | source-root: desktop-app 17 | env: 18 | NODE_ENV: development 19 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/CrossChrome.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default function CrossChrome({width, height, color, padding, margin}) { 4 | return ( 5 | 6 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /desktop-app/app/containers/UserPreferencesContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import UserPreferences from '../../components/UserPreferences'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | userPreferences: state.browser.userPreferences, 12 | devToolsConfig: state.browser.devToolsConfig, 13 | }; 14 | } 15 | 16 | function mapDispatchToProps(dispatch) { 17 | return bindActionCreators(BrowserActions, dispatch); 18 | } 19 | 20 | export default connect(mapStateToProps, mapDispatchToProps)(UserPreferences); 21 | -------------------------------------------------------------------------------- /desktop-app/app/settings/statusBarSettings.js: -------------------------------------------------------------------------------- 1 | import settings from 'electron-settings'; 2 | import {STATUS_BAR_VISIBILITY} from '../constants/settingKeys'; 3 | 4 | class StatusBarSettings { 5 | constructor() { 6 | const visibility = settings.get(STATUS_BAR_VISIBILITY); 7 | 8 | if (visibility === undefined) { 9 | settings.set(STATUS_BAR_VISIBILITY, true); 10 | } 11 | } 12 | 13 | getVisibility = () => settings.get(STATUS_BAR_VISIBILITY); 14 | 15 | setVisibility = visible => { 16 | settings.set(STATUS_BAR_VISIBILITY, visible); 17 | }; 18 | } 19 | 20 | const statusBarSettingsInstance = new StatusBarSettings(); 21 | 22 | export {statusBarSettingsInstance as statusBarSettings}; 23 | -------------------------------------------------------------------------------- /desktop-app/resources/dock-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/resources/scenery.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/components/PermissionPopup/styles.module.css: -------------------------------------------------------------------------------- 1 | .permissionPopup { 2 | position: absolute; 3 | border-radius: 4px; 4 | box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 5 | 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12); 6 | width: 20em; 7 | transition: opacity 0.5s ease-out; 8 | opacity: 0; 9 | height: 0; 10 | overflow: hidden; 11 | } 12 | 13 | .permissionPopupActive { 14 | opacity: 1; 15 | height: auto; 16 | } 17 | 18 | .permissionPopupTitle { 19 | margin: 14px; 20 | } 21 | 22 | .permissionPopupMsg { 23 | margin-bottom: 0 !important; 24 | font-size: 0.9rem !important; 25 | } 26 | 27 | .permissionPopupMsgContainer { 28 | padding: 0 14px !important; 29 | } 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: responsively 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /desktop-app/.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pr 8 | - discussion 9 | - e2e 10 | - enhancement 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /browser-extension/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Responsively Helper", 3 | "version": "0.0.2", 4 | "description": "An extension to open current browser page in Responsively app", 5 | "homepage_url": "https://responsively.app", 6 | "manifest_version": 2, 7 | "icons": { 8 | "128": "logo_128.png", 9 | "48": "logo_48.png", 10 | "16": "logo_16.png" 11 | }, 12 | "background": { 13 | "persistent": false, 14 | "scripts": [ 15 | "browser-polyfill.min.js", 16 | "background.js" 17 | ] 18 | }, 19 | "browser_action": { 20 | "default_icon": "logo_128.png", 21 | "default_title": "Open page in Responsively app", 22 | "default_popup": "popup.html" 23 | }, 24 | "permissions": [ 25 | "activeTab" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/GoArrow.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /desktop-app/resources/undock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # ✨ Pull Request 2 | 3 | ### 📓 Referenced Issue 4 | 5 | 6 | 7 | ### ℹ️ About the PR 8 | 9 | 10 | 11 | ### 🖼️ Testing Scenarios / Screenshots 12 | 13 | 14 | -------------------------------------------------------------------------------- /desktop-app/add-osx-cert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | KEY_CHAIN=build.keychain 4 | CERTIFICATE_P12=certificate.p12 5 | 6 | # Recreate the certificate from the secure environment variable 7 | echo $CERTIFICATE_OSX_P12 | base64 --decode > $CERTIFICATE_P12 8 | 9 | #create a keychain 10 | security create-keychain -p travis $KEY_CHAIN 11 | 12 | # Make the keychain the default so identities are found 13 | security default-keychain -s $KEY_CHAIN 14 | 15 | # Unlock the keychain 16 | security unlock-keychain -p travis $KEY_CHAIN 17 | 18 | security import $CERTIFICATE_P12 -k $KEY_CHAIN -P $CERTIFICATE_OSX_PASSWORD -T /usr/bin/codesign; 19 | 20 | security set-key-partition-list -S apple-tool:,apple: -s -k travis $KEY_CHAIN 21 | 22 | # remove certs 23 | rm -fr *.p12 24 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Filter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Filter({width, height, color, className}) { 4 | return ( 5 | 13 | 19 | 20 | ); 21 | } 22 | 23 | Filter.defaultProps = { 24 | color: 'currentColor', 25 | }; 26 | 27 | export default Filter; 28 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Gift.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | function Gift({width, height, color, className}) { 4 | return ( 5 | 6 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | Gift.defaultProps = { 21 | color: 'currentColor', 22 | }; 23 | 24 | export default Gift; 25 | -------------------------------------------------------------------------------- /desktop-app/app/store/configureStore.prod.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import {createStore, applyMiddleware} from 'redux'; 3 | import thunk from 'redux-thunk'; 4 | import createRootReducer from '../reducers'; 5 | 6 | const rootReducer = createRootReducer(); 7 | const heap = () => next => action => { 8 | window.requestIdleCallback(() => { 9 | if (window.heap) { 10 | window.heap.track(`ACTION-${action.type}`, { 11 | type: action.type, 12 | payload: JSON.stringify(action), 13 | }); 14 | } 15 | }); 16 | return next(action); 17 | }; 18 | const enhancer = applyMiddleware(thunk, heap); 19 | 20 | function configureStore(initialState) { 21 | return createStore(rootReducer, initialState, enhancer); 22 | } 23 | 24 | export default {configureStore}; 25 | -------------------------------------------------------------------------------- /desktop-app/app/utils/iconUtils.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DesktopIcon from '@material-ui/icons/DesktopWindows'; 3 | import MobileIcon from '@material-ui/icons/Smartphone'; 4 | import TabletIcon from '@material-ui/icons/TabletMac'; 5 | import {DEVICE_TYPE} from '../constants/devices'; 6 | 7 | export const getDeviceIcon = deviceType => { 8 | const iconProps = { 9 | style: {fontSize: 'inherit', paddingRight: 2}, 10 | }; 11 | switch (deviceType) { 12 | case DEVICE_TYPE.phone: 13 | return ; 14 | case DEVICE_TYPE.tablet: 15 | return ; 16 | case DEVICE_TYPE.desktop: 17 | return ; 18 | default: 19 | return null; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /desktop-app/app/components/NetworkThrottling/ProfileManager/styles.css: -------------------------------------------------------------------------------- 1 | .profileManagerContainer { 2 | height: 600px; 3 | padding: 20px; 4 | } 5 | 6 | .profilesContainer { 7 | max-height: 430px; 8 | overflow-y: auto; 9 | flex-grow: 1; 10 | } 11 | 12 | .profilesRow > th, 13 | td { 14 | padding-right: 16px !important; 15 | } 16 | 17 | .profilesHeader > tr > th { 18 | font-size: 20px; 19 | font-weight: bold; 20 | } 21 | 22 | .profilesRow > th.customProfile { 23 | cursor: pointer; 24 | } 25 | 26 | .saveButton { 27 | position: absolute !important; 28 | bottom: 25px; 29 | right: 25px; 30 | } 31 | 32 | .numericField * { 33 | text-align: right; 34 | font-size: 14px !important; 35 | } 36 | 37 | .titleField * { 38 | font-size: 14px !important; 39 | } 40 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Kebab.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default function Kebab({width, height, color, padding, margin}) { 4 | return ( 5 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /desktop-app/app/containers/NetworkConfigurationContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import NetworkConfiguration from '../../components/NetworkConfiguration'; 7 | import * as NetworkConfigActions from '../../actions/networkConfig'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | throttling: state.browser.networkConfiguration.throttling, 12 | proxy: state.browser.networkConfiguration.proxy, 13 | }; 14 | } 15 | 16 | function mapDispatchToProps(dispatch) { 17 | return bindActionCreators(NetworkConfigActions, dispatch); 18 | } 19 | 20 | export default connect( 21 | mapStateToProps, 22 | mapDispatchToProps 23 | )(NetworkConfiguration); 24 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/LightColorScheme.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin, className}) => ( 4 | 5 | 15 | 16 | 17 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Start.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Start({width, height, strokeColor, fillColor, padding, margin}) { 4 | return ( 5 | 17 | 18 | 22 | 23 | ); 24 | } 25 | 26 | export default Start; 27 | -------------------------------------------------------------------------------- /desktop-app/app/containers/NavigationControlsContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import * as BrowserActions from '../../actions/browser'; 7 | import NavigationControls from '../../components/NavigationControls'; 8 | 9 | function mapStateToProps(state) { 10 | const { 11 | navigatorStatus: {backEnabled, forwardEnabled}, 12 | devices, 13 | address, 14 | homepage, 15 | } = state.browser; 16 | return {backEnabled, forwardEnabled, devices, address, homepage}; 17 | } 18 | 19 | function mapDispatchToProps(dispatch) { 20 | return bindActionCreators(BrowserActions, dispatch); 21 | } 22 | 23 | export default connect(mapStateToProps, mapDispatchToProps)(NavigationControls); 24 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Bug.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | const Bug = ({width, height, color, padding, margin}) => ( 4 | 5 | 14 | 15 | 19 | 23 | 24 | 25 | 26 | ); 27 | 28 | Bug.defaultProps = { 29 | color: 'currentColor', 30 | }; 31 | 32 | export default Bug; 33 | -------------------------------------------------------------------------------- /desktop-app/app/components/DeviceManager/styles.css: -------------------------------------------------------------------------------- 1 | .container { 2 | margin: 50px; 3 | height: calc(100vh - 200px); 4 | } 5 | 6 | .content { 7 | height: 100%; 8 | justify-content: center; 9 | } 10 | 11 | .section { 12 | position: relative; 13 | padding: 0 20px; 14 | } 15 | 16 | .listTitle { 17 | display: flex; 18 | background: #7587ec; 19 | padding: 20px; 20 | margin: 0 auto; 21 | border-radius: 10px; 22 | color: white; 23 | align-items: flex-end; 24 | margin-bottom: 10px; 25 | justify-content: center; 26 | } 27 | 28 | .toolTip { 29 | background: #ffffff10; 30 | padding: 10px 40px; 31 | border-radius: 5px; 32 | margin: 0 auto 20px; 33 | text-align: center; 34 | font-size: 14px; 35 | color: #dedede; 36 | width: fit-content; 37 | } 38 | 39 | .editButton { 40 | font-size: 10px !important; 41 | padding: 5px !important; 42 | } 43 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Apple.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 15 | 16 | 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /desktop-app/app/shortcut-manager/shared.js: -------------------------------------------------------------------------------- 1 | export const REGISTER_CHANNEL = 'register-shortcut'; 2 | export const UNREGISTER_CHANNEL = 'unregister-shortcut'; 3 | export const REGISTER_REPLY_CHANNEL = 'register-shortcut-reply'; 4 | export const UNREGISTER_REPLY_CHANNEL = 'unregister-shortcut-reply'; 5 | export const GET_ALL_CHANNEL = 'get-all-shortcuts'; 6 | export const CLEAR_CHANNEL = 'clear-shortcuts'; 7 | export type ShortcutDefinition = { 8 | id: string, 9 | title: string, 10 | accelerators: string[], 11 | }; 12 | export type CommunicationResponse = { 13 | ok: boolean, 14 | id: string, 15 | }; 16 | 17 | export function validateDefinition(shortcut: ShortcutDefinition): boolean { 18 | return ( 19 | shortcut != null && 20 | shortcut.id != null && 21 | shortcut.title != null && 22 | (shortcut.accelerators || []).length !== 0 && 23 | shortcut.accelerators.every(x => x != null) 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /desktop-app/scripts/chocolatey/responsively/tools/chocolateyinstall.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = 'Stop'; 2 | 3 | $toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" 4 | $url = 'https://github.com/responsively-org/responsively-app/releases/download/v#VERSION#/ResponsivelyApp-Setup-#VERSION#.exe' 5 | $url64 = 'https://github.com/responsively-org/responsively-app/releases/download/v#VERSION#/ResponsivelyApp-Setup-#VERSION#.exe' 6 | 7 | $packageArgs = @{ 8 | packageName = $env:ChocolateyPackageName 9 | unzipLocation = $toolsDir 10 | fileType = 'exe' 11 | url = $url 12 | url64bit = $url64 13 | 14 | softwareName = 'responsively*' 15 | checksum = '#CHECKSUM#' 16 | checksumType = 'sha512' 17 | checksum64 = '#CHECKSUM#' 18 | checksumType64= 'sha512' 19 | 20 | silentArgs = "/S" 21 | validExitCodes= @(0, 3010, 1641) 22 | } 23 | 24 | Install-ChocolateyPackage @packageArgs -------------------------------------------------------------------------------- /desktop-app/internals/scripts/CheckBuiltsExist.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | // Check if the renderer and main bundles are built 3 | import path from 'path'; 4 | import chalk from 'chalk'; 5 | import fs from 'fs'; 6 | 7 | function CheckBuildsExist() { 8 | const mainPath = path.join(__dirname, '..', '..', 'app', 'main.prod.js'); 9 | const rendererPath = path.join( 10 | __dirname, 11 | '..', 12 | '..', 13 | 'app', 14 | 'dist', 15 | 'renderer.prod.js' 16 | ); 17 | 18 | if (!fs.existsSync(mainPath)) { 19 | throw new Error( 20 | chalk.whiteBright.bgRed.bold( 21 | 'The main process is not built yet. Build it by running "yarn build-main"' 22 | ) 23 | ); 24 | } 25 | 26 | if (!fs.existsSync(rendererPath)) { 27 | throw new Error( 28 | chalk.whiteBright.bgRed.bold( 29 | 'The renderer process is not built yet. Build it by running "yarn build-renderer"' 30 | ) 31 | ); 32 | } 33 | } 34 | 35 | CheckBuildsExist(); 36 | -------------------------------------------------------------------------------- /desktop-app/app/components/DeviceDrawer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import Divider from '@material-ui/core/Divider'; 4 | import PreviewerLayoutSelector from '../PreviewerLayoutSelector'; 5 | import DeviceManagerContainer from '../../containers/DeviceManagerContainer'; 6 | import QuickFilterDevicesContainer from '../../containers/QuickFilterDevicesContainer'; 7 | import DevicesIcon from '../icons/Devices'; 8 | import DevicesOverviewContainer from '../../containers/DevicesOverviewContainer'; 9 | import styles from './styles.css'; 10 | 11 | export default function DeviceDrawer({ 12 | browser: { 13 | previewer: {layout}, 14 | }, 15 | setPreviewLayout, 16 | }) { 17 | return ( 18 |
19 | 20 | setPreviewLayout(val.value)} 23 | /> 24 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /desktop-app/app/containers/DevToolResizerContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, {useEffect} from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {bindActionCreators} from 'redux'; 5 | 6 | import DevToolsResizer from '../../components/DevToolsResizer'; 7 | import * as BrowserActions from '../../actions/browser'; 8 | import {useMediaQuery} from '@material-ui/core'; 9 | import {DARK_THEME} from '../../constants/theme'; 10 | 11 | const Component = props => { 12 | const isDarkTheme = useMediaQuery(`(prefers-color-scheme: ${DARK_THEME})`); 13 | return ; 14 | }; 15 | 16 | function mapStateToProps(state) { 17 | return { 18 | ...state.browser.devToolsConfig, 19 | isInspecting: state.browser.isInspecting, 20 | devices: state.browser.devices, 21 | }; 22 | } 23 | 24 | function mapDispatchToProps(dispatch) { 25 | return bindActionCreators(BrowserActions, dispatch); 26 | } 27 | 28 | export default connect(mapStateToProps, mapDispatchToProps)(Component); 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/01-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41E Bug report" 3 | about: Report a bug in Responsively 4 | --- 5 | 6 | 11 | 12 | # 🐞 bug report 13 | 14 | ### ✍️ Description 15 | 16 | 17 | 18 | ### 🕵🏼‍♂️ Is this a regression? 19 | 20 | 21 | 22 | ### 🔬 Minimal Reproduction 23 | 24 | 25 | 26 | ### 🌍 Your Environment 27 | 28 | 29 |

30 | 
31 | 
32 | 33 | ### 🔥 Exception or Error or Screenshot 34 | 35 |

36 | 
37 | 
38 | -------------------------------------------------------------------------------- /desktop-app/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "files.associations": { 4 | ".babelrc": "jsonc", 5 | ".eslintrc": "jsonc", 6 | ".prettierrc": "jsonc", 7 | 8 | ".stylelintrc": "json", 9 | 10 | ".dockerignore": "ignore", 11 | ".eslintignore": "ignore", 12 | ".flowconfig": "ignore" 13 | }, 14 | 15 | "javascript.validate.enable": false, 16 | "javascript.format.enable": false, 17 | "typescript.validate.enable": false, 18 | "typescript.format.enable": false, 19 | 20 | "flow.useNPMPackagedFlow": true, 21 | "search.exclude": { 22 | ".git": true, 23 | ".eslintcache": true, 24 | "app/dist": true, 25 | "app/main.prod.js": true, 26 | "app/main.prod.js.map": true, 27 | "bower_components": true, 28 | "dll": true, 29 | "flow-typed": true, 30 | "release": true, 31 | "node_modules": true, 32 | "npm-debug.log.*": true, 33 | "test/**/__snapshots__": true, 34 | "yarn.lock": true 35 | }, 36 | "editor.defaultFormatter": "esbenp.prettier-vscode" 37 | } 38 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/DockBottom.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './styles.module.css'; 4 | 5 | export default function DockBottom({width, height, color, padding, margin}) { 6 | return ( 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /desktop-app/app/components/ClearNetworkCache/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import Button from '@material-ui/core/Button'; 4 | import CachedIcon from '@material-ui/icons/Cached'; 5 | import useCommonStyles from '../useCommonStyles'; 6 | 7 | function ClearNetworkCache(props) { 8 | const commonClasses = useCommonStyles(); 9 | 10 | return ( 11 |
12 |
13 | Network Cache 14 |
15 |
16 | 25 |
26 |
27 | ); 28 | } 29 | 30 | export default ClearNetworkCache; 31 | -------------------------------------------------------------------------------- /desktop-app/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /app/main.prod.js 3 | /app/main.prod.js.map 4 | /app/dist/.* 5 | /resources/.* 6 | /node_modules/webpack-cli 7 | /release/.* 8 | /dll/.* 9 | /release/.* 10 | /git/.* 11 | 12 | [include] 13 | 14 | [libs] 15 | 16 | [options] 17 | esproposal.class_static_fields=enable 18 | esproposal.class_instance_fields=enable 19 | esproposal.export_star_as=enable 20 | module.name_mapper.extension='css' -> '/internals/flow/CSSModule.js.flow' 21 | module.name_mapper.extension='styl' -> '/internals/flow/CSSModule.js.flow' 22 | module.name_mapper.extension='scss' -> '/internals/flow/CSSModule.js.flow' 23 | module.name_mapper.extension='png' -> '/internals/flow/WebpackAsset.js.flow' 24 | module.name_mapper.extension='jpg' -> '/internals/flow/WebpackAsset.js.flow' 25 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe 26 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue 27 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Pictures.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/TickAnimation/styles.css: -------------------------------------------------------------------------------- 1 | .iconCheck { 2 | text-align: center; 3 | margin: auto; 4 | width: 20px; 5 | height: 20px; 6 | fill-rule: evenodd; 7 | clip-rule: evenodd; 8 | stroke-linecap: round; 9 | stroke-linejoin: round; 10 | stroke-miterlimit: 1.5; 11 | } 12 | 13 | .iconCheck .circle { 14 | animation-name: circle; 15 | animation-duration: 2s; 16 | stroke-dashoffset: 0; 17 | stroke-dasharray: 1000; 18 | animation-timing-function: ease-in-out; 19 | fill: none; 20 | stroke-width: 16.67px; 21 | } 22 | 23 | .iconCheck .check { 24 | animation-name: check; 25 | animation-duration: 2s; 26 | stroke-dashoffset: 500; 27 | stroke-dasharray: 1000; 28 | animation-delay: 1s; 29 | animation-timing-function: ease-in-out; 30 | } 31 | 32 | @keyframes circle { 33 | from { 34 | stroke-dashoffset: 1000; 35 | } 36 | to { 37 | stroke-dashoffset: 0; 38 | } 39 | } 40 | 41 | @keyframes check { 42 | from { 43 | stroke-dashoffset: 0; 44 | } 45 | to { 46 | stroke-dashoffset: 500; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /desktop-app/.dockerignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | .eslintcache 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # OSX 31 | .DS_Store 32 | 33 | # flow-typed 34 | flow-typed/npm/* 35 | !flow-typed/npm/module_vx.x.x.js 36 | 37 | # App packaged 38 | release 39 | app/main.prod.js 40 | app/main.prod.js.map 41 | app/renderer.prod.js 42 | app/renderer.prod.js.map 43 | app/style.css 44 | app/style.css.map 45 | dist 46 | dll 47 | main.js 48 | main.js.map 49 | 50 | .idea 51 | npm-debug.log.* 52 | .*.dockerfile -------------------------------------------------------------------------------- /desktop-app/app/components/icons/DarkColorScheme.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin, className}) => ( 4 | 5 | 15 | 16 | 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /desktop-app/app/components/StatusBar/Announcement.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from 'react'; 2 | import cx from 'classnames'; 3 | import {shell} from 'electron'; 4 | import useStyles from './useStyles'; 5 | 6 | const Announcement = () => { 7 | const [data, setData] = useState(null); 8 | const classes = useStyles(); 9 | useEffect(() => { 10 | (async () => { 11 | try { 12 | const response = await ( 13 | await fetch('https://responsively.app/assets/appMessages.json') 14 | ).json(); 15 | setData(response.statusBarMessage); 16 | } catch (err) { 17 | console.log('Error fetching appMessages.json', err); 18 | } 19 | })(); 20 | }, []); 21 | 22 | if (!data) { 23 | return null; 24 | } 25 | 26 | return ( 27 |
shell.openExternal(data.link)} 30 | > 31 | 32 | {data.text} 33 | 34 |
35 | ); 36 | }; 37 | 38 | export default Announcement; 39 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Layout.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /desktop-app/app/components/NetworkConfiguration/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import ClearNetworkCache from '../ClearNetworkCache'; 4 | import NetworkThrottling from '../NetworkThrottling'; 5 | import NetworkProxy from '../NetworkProxy'; 6 | 7 | import styles from './styles.css'; 8 | 9 | export default function NetworkConfiguration({ 10 | throttling, 11 | proxy, 12 | onActiveThrottlingProfileChanged, 13 | onThrottlingProfilesListChanged, 14 | onClearNetworkCache, 15 | onToggleUseProxy, 16 | onProxyProfileChanged, 17 | }) { 18 | return ( 19 |
20 | 21 | 26 | 31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /desktop-app/app/components/PrefersColorSchemeSwitch/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import {ipcRenderer} from 'electron'; 3 | import Tooltip from '@material-ui/core/Tooltip'; 4 | import LightColorSchemeIcon from '../icons/LightColorScheme'; 5 | import DarkColorSchemeIcon from '../icons/DarkColorScheme'; 6 | 7 | export default function PrefersColorSchemeSwitch({iconProps}) { 8 | const [colorScheme, setColorScheme] = useState( 9 | window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' 10 | ); 11 | 12 | const handleSwitch = () => { 13 | setColorScheme(colorScheme === 'dark' ? 'light' : 'dark'); 14 | }; 15 | 16 | useEffect(() => { 17 | ipcRenderer.send('prefers-color-scheme-select', colorScheme); 18 | }, [colorScheme]); 19 | 20 | return ( 21 | 22 |
23 | {colorScheme === 'dark' ? ( 24 | 25 | ) : ( 26 | 27 | )} 28 |
29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /desktop-app/.eslintignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | .eslintcache 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # OSX 31 | .DS_Store 32 | 33 | # flow-typed 34 | flow-typed/npm/* 35 | !flow-typed/npm/module_vx.x.x.js 36 | 37 | # App packaged 38 | release 39 | app/main.prod.js 40 | app/main.prod.js.map 41 | app/renderer.prod.js 42 | app/renderer.prod.js.map 43 | app/style.css 44 | app/style.css.map 45 | dist 46 | dll 47 | main.js 48 | main.js.map 49 | lib 50 | 51 | .idea 52 | npm-debug.log.* 53 | __snapshots__ 54 | 55 | # Package.json 56 | package.json 57 | .travis.yml 58 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/DockRight.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './styles.module.css'; 4 | 5 | export default function DockRight({width, height, color, padding, margin}) { 6 | return ( 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /desktop-app/app/components/DeviceManager/OSIcon.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MobileIcon from '@material-ui/icons/Smartphone'; 3 | import AndroidIcon from '@material-ui/icons/Android'; 4 | import DesktopIcon from '@material-ui/icons/DesktopWindows'; 5 | import {useTheme} from '@material-ui/core/styles'; 6 | import AppleIcon from '../icons/Apple'; 7 | import WindowsIcon from '../icons/Windows'; 8 | import {OS} from '../../constants/devices'; 9 | 10 | function OSIcon({os, color}) { 11 | const theme = useTheme(); 12 | const _color = color || theme.palette.text.primary; 13 | const iconProps = { 14 | style: {fontSize: 'inherit', paddingRight: 2, _color}, 15 | height: '1em', 16 | }; 17 | 18 | switch (os) { 19 | case OS.ios: 20 | return ; 21 | case OS.android: 22 | return ; 23 | case OS.windowsPhone: 24 | return ; 25 | case OS.pc: 26 | return ; 27 | default: 28 | return null; 29 | } 30 | } 31 | 32 | export default OSIcon; 33 | -------------------------------------------------------------------------------- /desktop-app/configs/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Base webpack config used across other specific configs 3 | */ 4 | 5 | import path from 'path'; 6 | import webpack from 'webpack'; 7 | import {dependencies} from '../package.json'; 8 | 9 | export default { 10 | externals: [...Object.keys(dependencies || {})], 11 | 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.jsx?$/, 16 | exclude: /node_modules/, 17 | use: { 18 | loader: 'babel-loader', 19 | options: { 20 | cacheDirectory: true, 21 | }, 22 | }, 23 | }, 24 | ], 25 | }, 26 | 27 | output: { 28 | path: path.join(__dirname, '..', 'app'), 29 | // https://github.com/webpack/webpack/issues/1114 30 | libraryTarget: 'commonjs2', 31 | }, 32 | 33 | /** 34 | * Determine the array of extensions that should be used to resolve modules. 35 | */ 36 | resolve: { 37 | extensions: ['.js', '.jsx', '.json'], 38 | }, 39 | 40 | plugins: [ 41 | new webpack.EnvironmentPlugin({ 42 | NODE_ENV: 'production', 43 | }), 44 | 45 | new webpack.NamedModulesPlugin(), 46 | ], 47 | }; 48 | -------------------------------------------------------------------------------- /desktop-app/app/components/StatusBar/useStyles.js: -------------------------------------------------------------------------------- 1 | import {makeStyles} from '@material-ui/core/styles'; 2 | 3 | const useStyles = makeStyles({ 4 | statusBar: { 5 | height: '20px', 6 | display: 'flex', 7 | borderRadius: 0, 8 | boxShadow: '0 -3px 5px rgba(0, 0, 0, 0.35)', 9 | color: '#fffc', 10 | justifyContent: 'space-between', 11 | zIndex: 1, 12 | }, 13 | section: { 14 | display: 'flex', 15 | alignItems: 'center', 16 | margin: '0 5px', 17 | }, 18 | text: { 19 | display: 'flex', 20 | alignItems: 'center', 21 | cursor: 'default', 22 | color: 'grey', 23 | fill: 'grey', 24 | borderRadius: 2, 25 | height: '100%', 26 | padding: '0 5px', 27 | filter: 'grayscale(1)', 28 | }, 29 | link: { 30 | cursor: 'pointer', 31 | '&:hover': { 32 | color: 'lightgrey', 33 | fill: 'lightgrey', 34 | backgroundColor: '#000', 35 | filter: 'none', 36 | }, 37 | }, 38 | linkIcon: { 39 | fill: 'inherit', 40 | margin: '0 4px', 41 | }, 42 | linkText: { 43 | color: 'inherit', 44 | fontSize: '12px', 45 | }, 46 | }); 47 | 48 | export default useStyles; 49 | -------------------------------------------------------------------------------- /desktop-app/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | .eslintcache 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # OSX 31 | .DS_Store 32 | 33 | # flow-typed 34 | flow-typed/npm/* 35 | !flow-typed/npm/module_vx.x.x.js 36 | 37 | # App packaged 38 | release 39 | app/main.prod.js 40 | app/main.prod.js.map 41 | app/renderer.prod.js 42 | app/renderer.prod.js.map 43 | app/style.css 44 | app/style.css.map 45 | /dist 46 | app/dist 47 | dll 48 | main.js 49 | main.js.map 50 | 51 | .idea 52 | npm-debug.log.* 53 | package-lock.json 54 | 55 | # local configs 56 | setCreds.sh 57 | embedded.provisionprofile 58 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/TickAnimation/index.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | import styles from './styles.css'; 3 | 4 | export default ({width, height, color = '#ffffff80', padding}) => ( 5 | 6 | 17 | 18 | 19 | 27 | 28 | 35 | 36 | 37 | 38 | ); 39 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Proxy.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 18 | 19 | Layer 1 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /desktop-app/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-present C. T. Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /desktop-app/resources/inspect-element-chrome.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Zoom.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | -------------------------------------------------------------------------------- /desktop-app/app/components/UserPreferences/useStyles.js: -------------------------------------------------------------------------------- 1 | import {makeStyles} from '@material-ui/core/styles'; 2 | 3 | const useStyles = makeStyles(theme => ({ 4 | preferenceName: { 5 | fontSize: '14px', 6 | }, 7 | preferenceColor: { 8 | width: '24px', 9 | height: '20px', 10 | margin: '0 10px', 11 | border: 'transparent', 12 | '& input': { 13 | width: '24px', 14 | height: '26px', 15 | border: 'transparent', 16 | }, 17 | }, 18 | sectionTitle: { 19 | margin: '5px 0', 20 | }, 21 | sectionHeader: { 22 | '&:after': { 23 | content: '""', 24 | flex: 1, 25 | marginLeft: 5, 26 | height: 1, 27 | backgroundColor: theme.palette.text.primary, 28 | }, 29 | }, 30 | marginTop: { 31 | marginTop: '10px', 32 | }, 33 | permissionsSelectorSmallNote: { 34 | color: theme.palette.text.primary, 35 | margin: 0, 36 | fontSize: '0.75rem', 37 | marginTop: '10px', 38 | textAlign: 'left', 39 | fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif", 40 | fontWeight: 400, 41 | lineHeight: 1.66, 42 | letterSpacing: '0.03333em', 43 | }, 44 | })); 45 | 46 | export default useStyles; 47 | -------------------------------------------------------------------------------- /desktop-app/resources/inspect-element.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/components/Spinner/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CircularProgress from '@material-ui/core/CircularProgress'; 3 | import {makeStyles} from '@material-ui/core/styles'; 4 | 5 | export default function(props) { 6 | const classes = makeStyles({ 7 | root: { 8 | width: '100%', 9 | height: '100%', 10 | position: 'relative', 11 | display: 'flex', 12 | justifyContent: 'center', 13 | alignItems: 'center', 14 | }, 15 | top: { 16 | color: '#ffffff00', // '#eef3fd', 17 | }, 18 | bottom: { 19 | color: '#7587ec', // '#6798e5', 20 | animationDuration: '550ms', 21 | position: 'absolute', 22 | }, 23 | })(); 24 | 25 | return ( 26 |
27 | 35 | 43 |
44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /desktop-app/app/components/DevicesPreviewer/useStyles.js: -------------------------------------------------------------------------------- 1 | import {makeStyles} from '@material-ui/core/styles'; 2 | 3 | const useStyles = makeStyles(theme => ({ 4 | container: { 5 | display: 'flex', 6 | flex: '1', 7 | height: '100%', 8 | width: '100%', 9 | overflow: 'auto', 10 | flexDirection: 'column', 11 | }, 12 | flexigrid: { 13 | flexWrap: 'wrap', 14 | }, 15 | horizontal: { 16 | flexWrap: 'nowrap', 17 | }, 18 | devicesContainer: { 19 | display: 'flex', 20 | paddingBottom: '100px', 21 | }, 22 | tab: { 23 | display: 'none', 24 | margin: 'auto', 25 | }, 26 | activeTab: { 27 | display: 'block', 28 | }, 29 | reactTabs: { 30 | position: 'sticky', 31 | left: 0, 32 | top: 0, 33 | marginBottom: '10px', 34 | zIndex: '4', 35 | backgroundColor: theme.palette.background.l0, 36 | }, 37 | reactTabs__tab: { 38 | display: 'flex', 39 | alignItems: 'center', 40 | flexShrink: 0, 41 | bottom: 'unset', 42 | border: '1px solid #aaa', 43 | borderRadius: '5px 5px 0 0', 44 | }, 45 | reactTabs__tabList: { 46 | display: 'flex', 47 | marginBottom: 0, 48 | overflow: 'auto', 49 | }, 50 | })); 51 | 52 | export default useStyles; 53 | -------------------------------------------------------------------------------- /desktop-app/resources/cross-thin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /desktop-app/scripts/chocolatey/responsively/tools/chocolateyuninstall.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = 'Stop'; 2 | $packageArgs = @{ 3 | packageName = $env:ChocolateyPackageName 4 | softwareName = 'responsively*' 5 | fileType = 'EXE' 6 | silentArgs = "/S" 7 | validExitCodes= @(0, 3010, 1605, 1614, 1641) 8 | } 9 | 10 | $uninstalled = $false 11 | [array]$key = Get-UninstallRegistryKey -SoftwareName $packageArgs['softwareName'] 12 | 13 | if ($key.Count -eq 1) { 14 | $key | % { 15 | $packageArgs['file'] = "$($_.UninstallString)" 16 | 17 | if ($packageArgs['fileType'] -eq 'MSI') { 18 | $packageArgs['silentArgs'] = "$($_.PSChildName) $($packageArgs['silentArgs'])" 19 | $packageArgs['file'] = '' 20 | } else { 21 | 22 | } 23 | 24 | Uninstall-ChocolateyPackage @packageArgs 25 | } 26 | } elseif ($key.Count -eq 0) { 27 | Write-Warning "$packageName has already been uninstalled by other means." 28 | } elseif ($key.Count -gt 1) { 29 | Write-Warning "$($key.Count) matches found!" 30 | Write-Warning "To prevent accidental data loss, no programs will be uninstalled." 31 | Write-Warning "Please alert package maintainer the following keys were matched:" 32 | $key | % {Write-Warning "- $($_.DisplayName)"} 33 | } 34 | -------------------------------------------------------------------------------- /desktop-app/app/components/DevicesOverview/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import {useTheme} from '@material-ui/core/styles'; 4 | import DeviceManagerContainer from '../../containers/DeviceManagerContainer'; 5 | import DevicesIcon from '../icons/Devices'; 6 | import useCommonStyles from '../useCommonStyles'; 7 | 8 | function DevicesOverview(props) { 9 | const theme = useTheme(); 10 | const commonClasses = useCommonStyles(); 11 | 12 | return ( 13 |
14 |
15 | {' '} 16 | Devices 17 |
18 |
19 |
25 | {props.browser.devices.length} active device 26 | {props.browser.devices.length !== 1 && 's'} 27 | 28 |
29 |
30 |
31 | ); 32 | } 33 | 34 | export default DevicesOverview; 35 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Twitter.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default function Twitter({ 4 | width, 5 | height, 6 | color, 7 | padding, 8 | margin, 9 | className, 10 | }) { 11 | return ( 12 | 13 | 23 | 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /desktop-app/app/utils/proxyUtils.js: -------------------------------------------------------------------------------- 1 | export function proxyRuleToString(scheme, rule, defaultRule) { 2 | let str = scheme === 'default' ? '' : `${scheme}=`; 3 | if (rule.useDefault) return str + defaultRule; 4 | if (rule.protocol === 'direct') return `${str}direct://`; 5 | str = `${str}${rule.protocol}://${rule.server}`; 6 | if (rule.port != null) str = `${str}:${rule.port}`; 7 | return defaultRule !== '' ? `${str},${defaultRule}` : str; 8 | } 9 | 10 | export function convertToProxyConfig(profile) { 11 | if (!profile.active) { 12 | return { 13 | proxyRules: 'direct://', 14 | }; 15 | } 16 | const defaultStr = proxyRuleToString('default', profile.default, ''); 17 | const parts = [ 18 | proxyRuleToString('http', profile.http, defaultStr), 19 | proxyRuleToString('https', profile.https, defaultStr), 20 | proxyRuleToString('ftp', profile.ftp, defaultStr), 21 | ]; 22 | 23 | return { 24 | proxyRules: parts.join(';'), 25 | proxyBypassRules: (profile.bypassList || []).join(','), 26 | }; 27 | } 28 | 29 | export function getEmptyProxySchemeConfig(useDefault = false) { 30 | return { 31 | protocol: '', 32 | server: '', 33 | port: '', 34 | user: '', 35 | password: '', 36 | useDefault: !!useDefault, 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /desktop-app/app/components/ZoomInput/index.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {shallow, mount} from 'enzyme'; 4 | import {expect, assert} from 'chai'; 5 | import sinon from 'sinon'; 6 | 7 | import Slider from '@material-ui/core/Slider'; 8 | import BrowserZoom from '.'; 9 | 10 | describe('', () => { 11 | it('Renders label and the slider component ', () => { 12 | const wrapper = shallow(); 13 | expect(wrapper.find(Slider)).to.have.lengthOf(1); 14 | }); 15 | 16 | it('Calls the callback on slider change', () => { 17 | const onChange = sinon.spy(); 18 | const wrapper = mount(); 19 | wrapper.find('.MuiSlider-thumb').simulate('mousedown'); 20 | wrapper.find('.MuiSlider-thumb').simulate('mouseup'); 21 | expect(onChange).to.have.property('callCount', 1); 22 | }); 23 | 24 | /* it('Calls the callback with a number value', () => { 25 | const onChange = sinon.spy(); 26 | const wrapper = mount(); 27 | wrapper.find('.MuiSlider-thumb').simulate('mousedown'); 28 | wrapper.find('.MuiSlider-thumb').simulate('mouseup'); 29 | console.log('spy.args', onChange.args); 30 | assert(onChange.calledWith(100)); 31 | }); */ 32 | }); 33 | -------------------------------------------------------------------------------- /desktop-app/app/components/ScrollControls/index.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {shallow, mount} from 'enzyme'; 4 | import {expect, assert} from 'chai'; 5 | import sinon from 'sinon'; 6 | 7 | import Slider from '@material-ui/core/Slider'; 8 | import BrowserZoom from '.'; 9 | 10 | describe('', () => { 11 | it('Renders label and the slider component ', () => { 12 | const wrapper = shallow(); 13 | expect(wrapper.find(Slider)).to.have.lengthOf(1); 14 | }); 15 | 16 | it('Calls the callback on slider change', () => { 17 | const onChange = sinon.spy(); 18 | const wrapper = mount(); 19 | wrapper.find('.MuiSlider-thumb').simulate('mousedown'); 20 | wrapper.find('.MuiSlider-thumb').simulate('mouseup'); 21 | expect(onChange).to.have.property('callCount', 1); 22 | }); 23 | 24 | /* it('Calls the callback with a number value', () => { 25 | const onChange = sinon.spy(); 26 | const wrapper = mount(); 27 | wrapper.find('.MuiSlider-thumb').simulate('mousedown'); 28 | wrapper.find('.MuiSlider-thumb').simulate('mouseup'); 29 | console.log('spy.args', onChange.args); 30 | assert(onChange.calledWith(100)); 31 | }); */ 32 | }); 33 | -------------------------------------------------------------------------------- /desktop-app/app/components/NavigationControls/index.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import {shallow, mount} from 'enzyme'; 4 | import {expect, assert} from 'chai'; 5 | import sinon from 'sinon'; 6 | 7 | import Slider from '@material-ui/core/Slider'; 8 | import BrowserZoom from '.'; 9 | 10 | describe('', () => { 11 | it('Renders label and the slider component ', () => { 12 | const wrapper = shallow(); 13 | expect(wrapper.find(Slider)).to.have.lengthOf(1); 14 | }); 15 | 16 | it('Calls the callback on slider change', () => { 17 | const onChange = sinon.spy(); 18 | const wrapper = mount(); 19 | wrapper.find('.MuiSlider-thumb').simulate('mousedown'); 20 | wrapper.find('.MuiSlider-thumb').simulate('mouseup'); 21 | expect(onChange).to.have.property('callCount', 1); 22 | }); 23 | 24 | /* it('Calls the callback with a number value', () => { 25 | const onChange = sinon.spy(); 26 | const wrapper = mount(); 27 | wrapper.find('.MuiSlider-thumb').simulate('mousedown'); 28 | wrapper.find('.MuiSlider-thumb').simulate('mouseup'); 29 | console.log('spy.args', onChange.args); 30 | assert(onChange.calledWith(100)); 31 | }); */ 32 | }); 33 | -------------------------------------------------------------------------------- /desktop-app/app/constants/pubsubEvents.js: -------------------------------------------------------------------------------- 1 | export const SCROLL_DOWN = 'SCROLL_DOWN'; 2 | export const SCROLL_UP = 'SCROLL_UP'; 3 | export const NAVIGATION_BACK = 'NAVIGATION_BACK'; 4 | export const NAVIGATION_FORWARD = 'NAVIGATION_FORWARD'; 5 | export const NAVIGATION_RELOAD = 'NAVIGATION_RELOAD'; 6 | export const RELOAD_CSS = 'RELOAD_CSS'; 7 | export const ADDRESS_CHANGE = 'ADDRESS_CHANGE'; 8 | export const DELETE_STORAGE = 'DELETE_STORAGE'; 9 | export const SCREENSHOT_ALL_DEVICES = 'SCREENSHOT_ALL_DEVICES'; 10 | export const FLIP_ORIENTATION_ALL_DEVICES = 'FLIP_ORIENTATION_ALL_DEVICES'; 11 | export const TOGGLE_DEVICE_MUTED_STATE = 'TOGGLE_DEVICE_MUTED_STATE'; 12 | export const STOP_LOADING = 'STOP_LOADING'; 13 | 14 | export const SET_NETWORK_TROTTLING_PROFILE = 'SET_NETWORK_TROTTLING_PROFILE'; 15 | export const CLEAR_NETWORK_CACHE = 'CLEAR_NETWORK_CACHE'; 16 | export const OPEN_CONSOLE_FOR_DEVICE = 'OPEN_CONSOLE_FOR_DEVICE'; 17 | export const PROXY_AUTH_ERROR = 'PROXY_AUTH_ERROR'; 18 | 19 | // status bar events 20 | export const STATUS_BAR_VISIBILITY_CHANGE = 'status-bar-visibility-change'; 21 | 22 | export const HIDE_PERMISSION_POPUP_DUE_TO_RELOAD = 23 | 'HIDE_PERMISSION_POPUP_DUE_TO_RELOAD'; 24 | export const PERMISSION_MANAGEMENT_PREFERENCE_CHANGED = 25 | 'PERMISSION_MANAGEMENT_PREFERENCE_CHANGED'; 26 | -------------------------------------------------------------------------------- /desktop-app/app/components/AppNotification/styles.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | font-size: 14px; 3 | position: absolute; 4 | bottom: 35px; 5 | right: 25px; 6 | background: #7587ec; 7 | border-radius: 5px; 8 | word-wrap: break-word; 9 | box-shadow: inset 0 0 1px #000; 10 | padding: 10px 20px 20px 20px; 11 | min-width: 250px; 12 | max-width: 320px; 13 | } 14 | 15 | .titleContainer { 16 | cursor: pointer; 17 | font-size: 16px; 18 | font-weight: 500; 19 | margin: 10px; 20 | text-align: center; 21 | } 22 | 23 | .content { 24 | cursor: pointer; 25 | margin: 0 0 25px 0; 26 | width: 70%; 27 | text-align: center; 28 | } 29 | 30 | .responseButtons { 31 | padding: 8px; 32 | border: solid 1px white; 33 | border-radius: 100px; 34 | margin: 0 10px; 35 | min-width: 70px; 36 | justify-content: center; 37 | display: flex; 38 | cursor: pointer; 39 | } 40 | 41 | .responseButtons:hover { 42 | background: #6679e2; 43 | } 44 | 45 | .okButton { 46 | background: #efefef; 47 | border: solid 1px #efefef; 48 | color: black; 49 | } 50 | 51 | .okButton:hover { 52 | background: white; 53 | border: solid 1px white; 54 | color: #1e1e1e; 55 | } 56 | 57 | .responseButtonsContainer { 58 | display: flex; 59 | align-items: center; 60 | justify-content: space-between; 61 | } 62 | -------------------------------------------------------------------------------- /desktop-app/resources/focus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/resources/unfocus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop-app/app/utils/analytics.js: -------------------------------------------------------------------------------- 1 | import {app} from 'electron'; 2 | import path from 'path'; 3 | import ua from 'universal-analytics'; 4 | import {v4 as uuidv4} from 'uuid'; 5 | import fs from 'fs-extra'; 6 | 7 | const isDev = process.env.NODE_ENV !== 'production'; 8 | let uid = null; 9 | let appActive = false; 10 | 11 | try { 12 | const filePath = path.join(app.getPath('userData'), 'uid'); 13 | try { 14 | uid = fs.readFileSync(filePath, 'utf-8'); 15 | } catch (err) {} 16 | if (!uid) { 17 | uid = uuidv4(); 18 | fs.writeFileSync(filePath, uid); 19 | } 20 | } catch (err) { 21 | console.log('Error initializing analytics', err); 22 | } 23 | 24 | const visitor = ua('UA-150751006-1', uid); 25 | 26 | export const startSession = () => { 27 | appActive = true; 28 | if (isDev) { 29 | return; 30 | } 31 | visitor.event({ec: 'App', ea: 'Open', sessionControl: 'start'}).send(); 32 | }; 33 | 34 | export const endSession = () => { 35 | appActive = false; 36 | if (isDev) { 37 | return; 38 | } 39 | visitor.event({ec: 'App', ea: 'Close', sessionControl: 'end'}).send(); 40 | }; 41 | 42 | export const sendEvent = (ec, ea) => !isDev && visitor.event({ec, ea}).send(); 43 | 44 | setInterval(() => { 45 | if (!appActive) { 46 | return; 47 | } 48 | sendEvent('App', 'Ping'); 49 | }, 20000); 50 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Muted.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default function Muted({width, height, color, padding, margin}) { 4 | return ( 5 | 6 | 20 | 21 | 25 | 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Github.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default function Github({ 4 | width, 5 | height, 6 | color, 7 | padding, 8 | margin, 9 | className, 10 | }) { 11 | return ( 12 | 13 | 23 | 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /desktop-app/app/containers/StatusBarContainer/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, {useEffect} from 'react'; 3 | import {ipcRenderer} from 'electron'; 4 | import {connect} from 'react-redux'; 5 | import {bindActionCreators} from 'redux'; 6 | 7 | import StatusBar from '../../components/StatusBar'; 8 | import {toggleStatusBarVisibility as _toggleStatusBarVisibility} from '../../actions/statusBar'; 9 | import {STATUS_BAR_VISIBILITY_CHANGE} from '../../constants/pubsubEvents'; 10 | 11 | const StatusBarContainer = ({visible, zoomLevel, toggleStatusBarVisibility}) => { 12 | useEffect(() => { 13 | const handler = () => { 14 | toggleStatusBarVisibility(); 15 | }; 16 | 17 | ipcRenderer.on(STATUS_BAR_VISIBILITY_CHANGE, handler); 18 | 19 | return () => 20 | ipcRenderer.removeListener(STATUS_BAR_VISIBILITY_CHANGE, handler); 21 | }, []); 22 | 23 | return ; 24 | }; 25 | 26 | function mapStateToProps(state) { 27 | return { 28 | visible: state.statusBar.visible, 29 | zoomLevel: state.browser.zoomLevel 30 | }; 31 | } 32 | 33 | function mapDispatchToProps(dispatch) { 34 | return bindActionCreators( 35 | {toggleStatusBarVisibility: _toggleStatusBarVisibility}, 36 | dispatch 37 | ); 38 | } 39 | 40 | export default connect(mapStateToProps, mapDispatchToProps)(StatusBarContainer); 41 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/CrossThin.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/ScrollUp.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | -------------------------------------------------------------------------------- /desktop-app/app/containers/BookmarksBarContainer/index.js: -------------------------------------------------------------------------------- 1 | import React, {useCallback} from 'react'; 2 | import {connect} from 'react-redux'; 3 | import {bindActionCreators} from 'redux'; 4 | 5 | import * as BrowserActions from '../../actions/browser'; 6 | import * as BookmarksActions from '../../actions/bookmarks'; 7 | import BookmarksBar from '../../components/BookmarksBar'; 8 | 9 | const BookmarksBarContainer = props => { 10 | const handleBookmarkClick = useCallback(bookmark => { 11 | props.onAddressChange(bookmark.url); 12 | }, []); 13 | 14 | const handleBookmarkDelete = useCallback(bookmark => { 15 | props.toggleBookmarkUrl(bookmark.url); 16 | }, []); 17 | 18 | return ( 19 | 25 | ); 26 | }; 27 | 28 | function mapStateToProps(state) { 29 | return { 30 | bookmarks: state.bookmarks.bookmarks, 31 | }; 32 | } 33 | 34 | function mapDispatchToProps(dispatch) { 35 | return bindActionCreators( 36 | { 37 | onAddressChange: BrowserActions.onAddressChange, 38 | ...BookmarksActions, 39 | }, 40 | dispatch 41 | ); 42 | } 43 | 44 | export default connect( 45 | mapStateToProps, 46 | mapDispatchToProps 47 | )(BookmarksBarContainer); 48 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/Cross.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | 3 | export default ({width, height, color, padding, margin}) => ( 4 | 5 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ); 46 | -------------------------------------------------------------------------------- /desktop-app/app/components/icons/UnDock.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | 4 | import styles from './styles.module.css'; 5 | 6 | export default function UnDock({ 7 | width, 8 | height, 9 | color, 10 | padding, 11 | margin, 12 | style, 13 | selected, 14 | }) { 15 | return ( 16 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 41 | 42 | 43 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /desktop-app/app/components/ExtensionsManager/styles.css: -------------------------------------------------------------------------------- 1 | .extensionManagerIcon { 2 | margin-right: 8px; 3 | margin-left: 10px; 4 | width: 30px; 5 | height: 30px; 6 | } 7 | 8 | .extensionsLabel { 9 | margin: 34px 0 0; 10 | font-size: 13px; 11 | line-height: 13px; 12 | opacity: 0.5; 13 | } 14 | 15 | .extension { 16 | width: 100%; 17 | display: flex; 18 | justify-content: space-between; 19 | align-items: center; 20 | padding: 12px 0; 21 | border-bottom: 1px solid #303030; 22 | } 23 | 24 | .extension:last-child { 25 | border-bottom-width: 0; 26 | padding-bottom: 0; 27 | } 28 | 29 | .extensionName { 30 | font-size: 15px; 31 | } 32 | 33 | .extensionVersion { 34 | opacity: 0.7; 35 | font-size: 12px; 36 | margin-left: 8px; 37 | display: inline-block; 38 | } 39 | 40 | .extensionAdd { 41 | display: flex; 42 | justify-content: space-between; 43 | align-items: flex-start; 44 | margin-bottom: 6px; 45 | margin-top: 12px; 46 | } 47 | 48 | .extensionsNotice { 49 | margin-top: 12px !important; 50 | } 51 | 52 | .extensionsHelp { 53 | display: flex; 54 | flex-direction: column; 55 | width: 500px; 56 | padding: 12px; 57 | color: white; 58 | border-radius: 4px; 59 | background: #252526; 60 | box-shadow: 3px 3px 6px 1px black; 61 | } 62 | 63 | .extensionsHelpText { 64 | font-size: 12px; 65 | } 66 | 67 | .extensionsHelpImg { 68 | object-fit: contain; 69 | width: 480px; 70 | } 71 | -------------------------------------------------------------------------------- /desktop-app/app/components/PreviewerLayoutSelector/index.js: -------------------------------------------------------------------------------- 1 | import React, {useMemo} from 'react'; 2 | import {useTheme} from '@material-ui/core/styles'; 3 | import LayoutIcon from '../icons/Layout'; 4 | import { 5 | HORIZONTAL_LAYOUT, 6 | FLEXIGRID_LAYOUT, 7 | INDIVIDUAL_LAYOUT, 8 | } from '../../constants/previewerLayouts'; 9 | import Select from '../Select'; 10 | import useCommonStyles from '../useCommonStyles'; 11 | 12 | function PreviewerLayoutSelector(props) { 13 | const theme = useTheme(); 14 | const commonClasses = useCommonStyles(); 15 | const selectedOption = useMemo( 16 | () => options.find(option => option.value === props.value), 17 | [props.value] 18 | ); 19 | 20 | return ( 21 |
22 |
23 | 24 | Layout 25 |
26 |
27 |