Bug 1239464 - Close button for exiting the responsive design view; r=jryans

MozReview-Commit-ID: Fygjgc7FHzF
This commit is contained in:
Matteo Ferretti 2016-03-04 01:21:19 -05:00
Родитель 4fc06aef08
Коммит 67f2481ef2
15 изменённых файлов: 236 добавлений и 41 удалений

Просмотреть файл

@ -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");
});