Bug 1239441 - Implement landscape / portrait button that rotates the viewport r=jryans

This commit is contained in:
Gabriel Luong 2016-02-10 17:07:17 -05:00
Родитель 582d5628c5
Коммит 598883d5e8
15 изменённых файлов: 172 добавлений и 12 удалений

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

@ -17,6 +17,9 @@ createEnum([
// Add an additional viewport to display the document.
"ADD_VIEWPORT",
// Rotate the viewport.
"ROTATE_VIEWPORT",
], module.exports);
/**

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

@ -4,7 +4,7 @@
"use strict";
const { ADD_VIEWPORT } = require("./index");
const { ADD_VIEWPORT, ROTATE_VIEWPORT } = require("./index");
module.exports = {
@ -17,4 +17,14 @@ module.exports = {
};
},
/**
* Rotate the viewport.
*/
rotateViewport(id) {
return {
type: ROTATE_VIEWPORT,
id,
};
},
};

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

@ -8,6 +8,7 @@ const { createClass, createFactory, PropTypes } =
require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { rotateViewport } = require("./actions/viewports");
const Types = require("./types");
const Viewports = createFactory(require("./components/viewports"));
@ -22,6 +23,7 @@ let App = createClass({
render() {
let {
dispatch,
location,
viewports,
} = this.props;
@ -31,6 +33,7 @@ let App = createClass({
return Viewports({
location,
viewports,
onRotateViewport: id => dispatch(rotateViewport(id)),
});
},

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

@ -6,6 +6,7 @@
DevToolsModules(
'browser.js',
'viewport-toolbar.js',
'viewport.js',
'viewports.js',
)

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

@ -0,0 +1,34 @@
/* 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 { DOM: dom, createClass, PropTypes } =
require("devtools/client/shared/vendor/react");
module.exports = createClass({
displayName: "ViewportToolbar",
propTypes: {
onRotateViewport: PropTypes.func.isRequired,
},
render() {
let {
onRotateViewport,
} = this.props;
return dom.div(
{
className: "viewport-toolbar",
},
dom.button({
className: "viewport-rotate-button viewport-toolbar-button",
onClick: onRotateViewport,
})
);
},
});

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

@ -9,6 +9,7 @@ const { DOM: dom, createClass, createFactory, PropTypes } =
const Types = require("../types");
const Browser = createFactory(require("./browser"));
const ViewportToolbar = createFactory(require("./viewport-toolbar"));
module.exports = createClass({
@ -17,22 +18,22 @@ module.exports = createClass({
propTypes: {
location: Types.location.isRequired,
viewport: PropTypes.shape(Types.viewport).isRequired,
onRotateViewport: PropTypes.func.isRequired,
},
render() {
let {
location,
viewport,
onRotateViewport,
} = this.props;
// Additional elements will soon appear here around the Browser, like drag
// handles, etc.
return dom.div(
{
className: "viewport"
},
dom.div({
className: "viewport-header",
ViewportToolbar({
onRotateViewport,
}),
Browser({
location,

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

@ -17,23 +17,26 @@ module.exports = createClass({
propTypes: {
location: Types.location.isRequired,
viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
onRotateViewport: PropTypes.func.isRequired,
},
render() {
let {
location,
viewports,
onRotateViewport,
} = this.props;
return dom.div(
{
id: "viewports",
},
viewports.map((viewport, index) => {
viewports.map(viewport => {
return Viewport({
key: index,
key: viewport.id,
location,
viewport,
onRotateViewport: () => onRotateViewport(viewport.id),
});
})
);

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

@ -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(
'rotate-viewport.svg',
)

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

@ -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" width="16" height="16" viewBox="0 0 16 16">
<path d="M12.3 11.5l-2.2-8.2-.3-.3c-.1-.1-.2-.1-.4-.1L4 4.4c-.2.1-.4.4-.3.6l2.2 8.2c0 .1.1.2.2.3.1 0 .2.1.3.1h.1l5.4-1.5c.3 0 .5-.3.4-.6zM9.2 4.1l1.5 5.5-4.4 1.2-1.5-5.5 4.4-1.2zm-2.4 8.4l-.3-1.1 4.4-1.2.3 1.1-4.4 1.2zM3.7 13.7c-1.2 0-3.4-.6-3.7-2.8-.3-2.2 1.3-3.3 2.1-3.5.2-.1.4.1.5.3.1.2-.1.4-.3.5-.1 0-1.8.6-1.6 2.7.2 1.5 1.6 1.9 2.4 2l-.7-2.4c0-.2.2-.5.4-.5.2-.1.4 0 .5.2l.9 3c0 .1 0 .3-.1.4-.1.1-.2.1-.4.1zM12.3 3.1c1.2 0 3.4.6 3.7 2.8.3 2.2-1.3 3.3-2.1 3.5-.2.1-.4-.1-.5-.3-.1-.2.1-.4.3-.5.1 0 1.8-.6 1.6-2.7-.2-1.5-1.6-1.9-2.4-2l.7 2.4c.1.2-.1.4-.3.5-.2.1-.4-.1-.5-.3l-.9-3c0-.1 0-.3.1-.4h.3z"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 908 B

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

@ -1,6 +1,18 @@
/* TODO: May break up into component local CSS. Pending future discussions by
* React component group on how to best handle CSS. */
/**
* CSS Variables specific to the responsive design mode
*/
.theme-light {
--viewport-box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26);
}
.theme-dark {
--viewport-box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26);
}
html, body {
margin: 0;
height: 100%;
@ -42,14 +54,46 @@ body {
/* Align all viewports to the top */
vertical-align: top;
border: 1px solid var(--theme-splitter-color);
box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26);
box-shadow: var(--viewport-box-shadow);
}
.viewport-header {
/**
* Viewport Toolbar
*/
.viewport-toolbar {
background-color: var(--theme-toolbar-background);
border-bottom: 1px solid var(--theme-splitter-color);
color: var(--theme-body-color-alt);
color: var(--theme-body-color);
display: flex;
flex-direction: row;
justify-content: flex-end;
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-image: url("./images/rotate-viewport.svg");
}
.browser {

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

@ -7,6 +7,7 @@
DIRS += [
'actions',
'components',
'images',
'reducers',
]

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

@ -4,10 +4,13 @@
"use strict";
const { ADD_VIEWPORT } = require("../actions/index");
const { ADD_VIEWPORT, ROTATE_VIEWPORT } = require("../actions/index");
let nextViewportId = 0;
const INITIAL_VIEWPORTS = [];
const INITIAL_VIEWPORT = {
id: nextViewportId++,
width: 320,
height: 480,
};
@ -19,7 +22,20 @@ let reducers = {
if (viewports.length === 1) {
return viewports;
}
return [...viewports, INITIAL_VIEWPORT];
return [...viewports, Object.assign({}, INITIAL_VIEWPORT)];
},
[ROTATE_VIEWPORT](viewports, { id }) {
return viewports.map(viewport => {
if (viewport.id !== id) {
return viewport;
}
return Object.assign({}, viewport, {
width: viewport.height,
height: viewport.width,
});
});
},
};

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

@ -0,0 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test rotating the viewport.
const { addViewport, rotateViewport } =
require("devtools/client/responsive.html/actions/viewports");
add_task(function*() {
let store = Store();
const { getState, dispatch } = store;
dispatch(addViewport());
let viewport = getState().viewports[0];
equal(viewport.width, 320, "Default width of 320");
equal(viewport.height, 480, "Default height of 480");
dispatch(rotateViewport(0));
viewport = getState().viewports[0];
equal(viewport.width, 480, "Rotated width of 480");
equal(viewport.height, 320, "Rotated height of 320");
});

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

@ -6,3 +6,4 @@ firefox-appdir = browser
[test_add_viewport.js]
[test_change_location.js]
[test_rotate_viewport.js]

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

@ -14,6 +14,9 @@ const { PropTypes } = require("devtools/client/shared/vendor/react");
*/
exports.viewport = {
// The id of the viewport
id: PropTypes.number.isRequired,
// The width of the viewport
width: PropTypes.number,