зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1239464 - Close button for exiting the responsive design view; r=jryans
MozReview-Commit-ID: Fygjgc7FHzF
This commit is contained in:
Родитель
4fc06aef08
Коммит
67f2481ef2
|
@ -0,0 +1,19 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# LOCALIZATION NOTE These strings are used inside the Responsive Design Mode,
|
||||
# available from the Web Developer sub-menu -> 'Responsive Design Mode'.
|
||||
#
|
||||
# The correct localization of this file might be to keep it in
|
||||
# English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (responsive.title): the title displayed in the global
|
||||
# toolbar
|
||||
responsive.title=Responsive Design Mode
|
||||
|
||||
# LOCALIZATION NOTE (responsive.exit): tooltip text of the exit button.
|
||||
responsive.exit=Close Responsive Design Mode
|
|
@ -4,13 +4,14 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { createClass, createFactory, PropTypes } =
|
||||
const { createClass, createFactory, PropTypes, DOM: dom } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const { resizeViewport, rotateViewport } = require("./actions/viewports");
|
||||
const Types = require("./types");
|
||||
const Viewports = createFactory(require("./components/viewports"));
|
||||
const GlobalToolbar = createFactory(require("./components/global-toolbar"));
|
||||
|
||||
let App = createClass({
|
||||
|
||||
|
@ -19,6 +20,7 @@ let App = createClass({
|
|||
propTypes: {
|
||||
location: Types.location.isRequired,
|
||||
viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
|
||||
onExit: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -26,17 +28,24 @@ let App = createClass({
|
|||
dispatch,
|
||||
location,
|
||||
viewports,
|
||||
onExit,
|
||||
} = this.props;
|
||||
|
||||
// For the moment, the app is just the viewports. This seems likely to
|
||||
// change assuming we add a global toolbar or something similar.
|
||||
return Viewports({
|
||||
location,
|
||||
viewports,
|
||||
onRotateViewport: id => dispatch(rotateViewport(id)),
|
||||
onResizeViewport: (id, width, height) =>
|
||||
dispatch(resizeViewport(id, width, height)),
|
||||
});
|
||||
return dom.div(
|
||||
{
|
||||
id: "app",
|
||||
},
|
||||
GlobalToolbar({
|
||||
onExit,
|
||||
}),
|
||||
Viewports({
|
||||
location,
|
||||
viewports,
|
||||
onRotateViewport: id => dispatch(rotateViewport(id)),
|
||||
onResizeViewport: (id, width, height) =>
|
||||
dispatch(resizeViewport(id, width, height)),
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { getStr } = require("./utils/l10n");
|
||||
const { DOM: dom, createClass, PropTypes } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
|
||||
module.exports = createClass({
|
||||
|
||||
displayName: "GlobalToolbar",
|
||||
|
||||
propTypes: {
|
||||
onExit: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
render() {
|
||||
let {
|
||||
onExit,
|
||||
} = this.props;
|
||||
|
||||
return dom.header(
|
||||
{
|
||||
id: "global-toolbar",
|
||||
className: "toolbar",
|
||||
},
|
||||
dom.span(
|
||||
{
|
||||
className: "title",
|
||||
},
|
||||
getStr("responsive.title")),
|
||||
dom.button({
|
||||
id: "global-exit-button",
|
||||
className: "toolbar-button",
|
||||
title: getStr("responsive.exit"),
|
||||
onClick: onExit,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
});
|
|
@ -4,8 +4,13 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'utils',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'browser.js',
|
||||
'global-toolbar.js',
|
||||
'resizable-viewport.js',
|
||||
'viewport-dimension.js',
|
||||
'viewport-toolbar.js',
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const STRINGS_URI = "chrome://devtools/locale/responsive.properties";
|
||||
|
||||
const {
|
||||
ViewHelpers
|
||||
} = require("resource://devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
|
||||
const L10N = new ViewHelpers.L10N(STRINGS_URI);
|
||||
|
||||
module.exports = {
|
||||
getStr: (...args) => L10N.getStr(...args),
|
||||
getFormatStr: (...args) => L10N.getFormatStr(...args),
|
||||
getFormatStrWithNumbers: (...args) => L10N.getFormatStrWithNumbers(...args),
|
||||
numberWithDecimals: (...args) => L10N.numberWithDecimals(...args),
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'l10n.js',
|
||||
)
|
|
@ -25,7 +25,7 @@ module.exports = createClass({
|
|||
className: "viewport-toolbar",
|
||||
},
|
||||
dom.button({
|
||||
className: "viewport-rotate-button viewport-toolbar-button",
|
||||
className: "viewport-rotate-button toolbar-button",
|
||||
onClick: onRotateViewport,
|
||||
})
|
||||
);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path d="M8.9 8l5-5c.2-.2.2-.6 0-.9-.2-.2-.6-.2-.9 0l-5 5-5-5c-.2-.2-.6-.2-.9 0-.2.3-.2.7 0 .9l5 5-5 5c-.2.2-.2.6 0 .9.1.1.3.1.5.1.1 0 .3 0 .4-.2l5-5 5 5c.1.1.3.2.4.2.2 0 .3-.1.4-.2.2-.2.2-.6 0-.9L8.9 8z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 488 B |
|
@ -5,6 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'close.svg',
|
||||
'grippers.svg',
|
||||
'rotate-viewport.svg',
|
||||
)
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
*/
|
||||
|
||||
.theme-light {
|
||||
--viewport-box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26);
|
||||
--box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26);
|
||||
--viewport-dimension-color: var(--theme-splitter-color);
|
||||
--viewport-dimension-editing-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
--viewport-box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26);
|
||||
--box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26);
|
||||
--viewport-dimension-color: var(--theme-body-color);
|
||||
--viewport-dimension-editing-color: var(--theme-selection-color);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#root,
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
|
@ -37,6 +38,60 @@ body {
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common style for toolbar buttons
|
||||
*/
|
||||
|
||||
.toolbar-button {
|
||||
border: none;
|
||||
display: block;
|
||||
margin: 1px 3px;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
opacity: 0.8;
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.toolbar-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toolbar-button:active {
|
||||
background-color: var(--theme-selection-background);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Toolbar
|
||||
*/
|
||||
|
||||
#global-toolbar {
|
||||
background-color: var(--theme-toolbar-background);
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
border-radius: 2px;
|
||||
color: var(--theme-body-color-alt);
|
||||
box-shadow: var(--box-shadow);
|
||||
margin: 30px 0;
|
||||
padding: 4px 8px;
|
||||
display: inline-flex;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
#global-toolbar > .title {
|
||||
border-right: 1px solid var(--theme-splitter-color);
|
||||
padding: 1px 6px 0 2px;
|
||||
}
|
||||
|
||||
#global-toolbar .toolbar-button {
|
||||
margin: 0 0 0 4px;
|
||||
}
|
||||
|
||||
#global-exit-button {
|
||||
mask: url("./images/close.svg");
|
||||
}
|
||||
|
||||
#viewports {
|
||||
|
@ -65,7 +120,7 @@ body {
|
|||
|
||||
.resizable-viewport {
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
box-shadow: var(--viewport-box-shadow);
|
||||
box-shadow: var(--box-shadow);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
@ -83,27 +138,6 @@ body {
|
|||
height: 18px;
|
||||
}
|
||||
|
||||
.viewport-toolbar-button {
|
||||
border: none;
|
||||
display: block;
|
||||
margin: 1px 3px;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
opacity: 0.8;
|
||||
background-color: var(--theme-body-color);
|
||||
transition: background 0.25s ease;
|
||||
}
|
||||
|
||||
.viewport-toolbar-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.viewport-toolbar-button:active {
|
||||
background-color: var(--theme-selection-background);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.viewport-rotate-button {
|
||||
mask: url("./images/rotate-viewport.svg");
|
||||
}
|
||||
|
|
|
@ -32,9 +32,11 @@ let bootstrap = {
|
|||
init() {
|
||||
this.telemetry.toolOpened("responsive");
|
||||
let store = this.store = Store();
|
||||
let app = createElement(App);
|
||||
let app = App({
|
||||
onExit: () => window.postMessage({type: "exit"}, "*"),
|
||||
});
|
||||
let provider = createElement(Provider, { store }, app);
|
||||
ReactDOM.render(provider, document.querySelector("#app"));
|
||||
ReactDOM.render(provider, document.querySelector("#root"));
|
||||
},
|
||||
|
||||
destroy() {
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
src="./index.js"></script>
|
||||
</head>
|
||||
<body class="theme-body" role="application">
|
||||
<div id="app"/>
|
||||
<div id="root"/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -18,7 +18,7 @@ const TOOL_URL = "chrome://devtools/content/responsive.html/index.xhtml";
|
|||
* from devtools/client/responsivedesign/responsivedesign.jsm delegates to this
|
||||
* object when the pref "devtools.responsive.html.enabled" is true.
|
||||
*/
|
||||
exports.ResponsiveUIManager = {
|
||||
const ResponsiveUIManager = exports.ResponsiveUIManager = {
|
||||
activeTabs: new Map(),
|
||||
|
||||
/**
|
||||
|
@ -138,8 +138,7 @@ exports.ResponsiveUIManager = {
|
|||
|
||||
// GCLI commands in ../responsivedesign/resize-commands.js listen for events
|
||||
// from this object to know when the UI for a tab has opened or closed.
|
||||
EventEmitter.decorate(exports.ResponsiveUIManager);
|
||||
|
||||
EventEmitter.decorate(ResponsiveUIManager);
|
||||
/**
|
||||
* ResponsiveUI manages the responsive design tool for a specific tab. The
|
||||
* actual tool itself lives in a separate chrome:// document that is loaded into
|
||||
|
@ -198,6 +197,7 @@ ResponsiveUI.prototype = {
|
|||
yield tabLoaded(this.tab);
|
||||
let toolWindow = this.toolWindow = tabBrowser.contentWindow;
|
||||
toolWindow.addInitialViewport(contentURI);
|
||||
toolWindow.addEventListener("message", this);
|
||||
}),
|
||||
|
||||
destroy() {
|
||||
|
@ -209,6 +209,21 @@ ResponsiveUI.prototype = {
|
|||
this.toolWindow = null;
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
let { tab, window } = this;
|
||||
let toolWindow = tab.linkedBrowser.contentWindow;
|
||||
|
||||
if (event.origin !== "chrome://devtools") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.data.type) {
|
||||
case "exit":
|
||||
toolWindow.removeEventListener(event.type, this);
|
||||
ResponsiveUIManager.closeIfNeeded(window, tab);
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function tabLoaded(tab) {
|
||||
|
|
|
@ -4,4 +4,5 @@ subsuite = devtools
|
|||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_exit_button.js]
|
||||
[browser_viewport_basics.js]
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test global exit button
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
addRDMTask(TEST_URL, function*({ ui, manager }) {
|
||||
let { toolWindow } = ui;
|
||||
let { store } = toolWindow;
|
||||
|
||||
// Wait until the viewport has been added
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
let browser = toolWindow.document.querySelector(".browser");
|
||||
let exitButton = toolWindow.document.getElementById("global-exit-button");
|
||||
|
||||
yield waitForFrameLoad(browser, TEST_URL);
|
||||
|
||||
ok(manager.isActiveForTab(ui.tab),
|
||||
"Responsive Design Mode active for the tab");
|
||||
|
||||
exitButton.click();
|
||||
|
||||
yield once(manager, "off");
|
||||
|
||||
ok(!manager.isActiveForTab(ui.tab),
|
||||
"Responsive Design Mode is not active for the tab");
|
||||
});
|
Загрузка…
Ссылка в новой задаче