Bottom panel selector on mobile devices

This commit is contained in:
JannisX11 2020-10-11 16:54:52 +02:00
parent 7a60e64771
commit a04974aab2
10 changed files with 106 additions and 133 deletions

@ -39,7 +39,7 @@
display: none;
}
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
dialog {
width: 100% !important;
}
@ -868,7 +868,7 @@
height: 26px;
vertical-align: text-top;
}
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
dialog#action_selector {
top: 26px;
}

@ -199,7 +199,7 @@
pointer-events: none;
}
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
#quick_message_box {
bottom: 26px;
top: unset;

@ -46,7 +46,7 @@
::selection {
background: var(--color-accent);
}
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
::-webkit-scrollbar {
width: 0;
height: 0;

@ -249,7 +249,7 @@ License: MIT
.sp-cf { *zoom: 1; }
/* Mobile devices, make hue slider bigger so it is easier to slide */
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
.sp-color { right: 40%; }
.sp-hue { left: 63%; }
.sp-fill { padding-top: 60%; }

@ -80,6 +80,7 @@
min-width: 100px;
display: flex;
flex-direction: column;
position: relative;
}
div#center > div {
max-height: 100%;
@ -258,15 +259,16 @@
}
/*Mobile*/
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
#page_wrapper {
display: grid;
grid-template-rows: auto minmax(200px, 5000px) 26px;
grid-template-rows: auto minmax(200px, 5000px) 26px 36px;
grid-template-areas:
"toolbar"
"center"
"status_bar";
"status_bar"
"panel_selector";
grid-template-columns: auto !important;
border: none;
}
@ -279,7 +281,7 @@
#main_toolbar > div.tools {
position: absolute;
z-index: 2;
bottom: 26px;
bottom: 62px;
right: 0px;
}
#main_toolbar > div.mobile_side {
@ -291,6 +293,10 @@
#main_toolbar > div.tool_options {
background-color: var(--color-back);
}
.preview .preview_menu {
left: 0;
right: unset;
}
.resizer.vertical {
display: none;
}
@ -301,25 +307,40 @@
width: calc(100% - 40px);
display: none;
}
/*Left*/
#page_wrapper.show_left {
grid-template-areas: "toolbar" "left_bar" "status_bar";
#panel_selector_bar {
display: flex;
grid-area: panel_selector;
}
#page_wrapper.show_left #center {
#panel_selector_bar .panel_selector {
height: 36px;
flex: 36px 1 0;
text-align: center;
cursor: default;
color: var(--color-text);
}
#panel_selector_bar .panel_selector.selected {
border-bottom: 3px solid var(--color-accent);
}
.panel_selector:only-child {
display: none;
}
#page_wrapper.show_left #left_bar {
display: flex;
#panel_selector_bar .panel_selector .icon_wrapper {
margin-top: 6px;
}
/*Right*/
#page_wrapper.show_right {
grid-template-areas: "toolbar" "right_bar" "status_bar";
div#mobile_panel_overlay {
position: absolute;
z-index: 19;
top: 0;
left: 0;
right: 40px;
bottom: 0;
background: var(--color-ui);
}
#page_wrapper.show_right #center {
display: none;
}
#page_wrapper.show_right #right_bar {
display: flex;
div#mobile_panel_overlay > .panel {
height: 100%;
}
}
@ -520,7 +541,7 @@
#start_screen i.start_screen_close_button:not(:hover) {
opacity: 0.8;
}
@media (max-device-width: 480px) {
@media (max-device-width: 640px) {
#start_screen {
width: calc(100% - 40px);
}

@ -65,6 +65,10 @@
<script src="js/interface/themes.js"></script>
<script src="js/blockbench.js"></script>
<script src="js/modes.js"></script>
<script src="js/api.js"></script>
<script src="js/file_system.js"></script>
<script src="js/interface/panels.js"></script>
<script src="js/interface/interface.js"></script>
<script src="js/interface/keyboard.js"></script>
<script src="js/interface/settings.js"></script>
<script src="js/interface/dialog.js"></script>
@ -79,10 +83,6 @@
}
</script>
<script src="js/api.js"></script>
<script src="js/file_system.js"></script>
<script src="js/interface/panels.js"></script>
<script src="js/interface/interface.js"></script>
<script src="js/edit_sessions.js"></script>
<script src="js/outliner/outliner.js"></script>
<script src="js/outliner/group.js"></script>
@ -960,6 +960,7 @@
</section>
</content>
</div>
<div id="mobile_panel_overlay" hidden></div>
</div>
<div id="status_bar" @contextmenu="Interface.status_bar.menu.show(event)">
@ -993,6 +994,15 @@
</div>
<div id="status_progress" v-if="Prop.progress" v-bind:style="{width: Prop.progress*100+'%'}"></div>
</div>
<div id="panel_selector_bar" hidden>
<div class="panel_selector" :class="{selected: selected == null}" @click="select(null)">
<div class="icon_wrapper"><i class="material-icons icon">3d_rotation</i></div>
</div>
<div class="panel_selector" :class="{selected: selected == panel.id}" v-for="panel in all_panels" v-if="Condition(panel.condition)" @click="select(panel)">
<div class="icon_wrapper" v-html="Blockbench.getIconNode(panel.icon).outerHTML"></div>
</div>
</div>
</div>

@ -1,6 +1,6 @@
const Blockbench = {
isWeb: !isApp,
isMobile: window.innerWidth <= 480,
isMobile: window.innerWidth <= 640,
version: appVersion,
platform: 'web',
flags: [],

@ -205,6 +205,10 @@ function setupInterface() {
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
setupPanels()
if (Blockbench.isMobile) {
setupMobilePanelSelector()
}
for (var key in Interface.Resizers) {
var resizer = Interface.Resizers[key]

@ -47,6 +47,10 @@ class Mode extends KeybindItem {
if (typeof this.onSelect === 'function') {
this.onSelect()
}
if (Blockbench.isMobile) {
Interface.PanelSelectorVue.$forceUpdate();
Interface.PanelSelectorVue.select(null);
}
updateInterface()
Canvas.updateRenderSides()

142
js/web.js

@ -71,112 +71,46 @@ function showSaveDialog(close) {
}
}
BARS.defineActions(function() {
function setupMobilePanelSelector() {
if (Blockbench.isMobile) {
var page_wrapper = $('#page_wrapper')
new Action('sidebar_left', {
icon: 'burst_mode',
category: 'view',
condition: () => !Modes.start,
click: function () {
page_wrapper.removeClass('show_right')
page_wrapper.toggleClass('show_left')
var s = page_wrapper.hasClass('show_left')
$('#left_bar').css('margin-left', '-400px')
$('#left_bar').animate({'margin-left': 0}, 160)
this.nodes.forEach(n => {
$(n).toggleClass('sel', s)
})
BarItems.sidebar_right.nodes.forEach(n => {
$(n).removeClass('sel')
})
updateInterfacePanels()
resizeWindow()
}
})
new Action('sidebar_right', {
icon: 'view_list',
category: 'view',
condition: () => !Modes.start,
click: function () {
page_wrapper.removeClass('show_left')
page_wrapper.toggleClass('show_right')
var s = page_wrapper.hasClass('show_right')
$('#right_bar').css('margin-left', '400px')
$('#right_bar').animate({'margin-left': 0}, 160)
this.nodes.forEach(n => {
$(n).toggleClass('sel', s)
})
BarItems.sidebar_left.nodes.forEach(n => {
$(n).removeClass('sel')
})
updateInterfacePanels()
resizeWindow()
}
})
$('.panel#element').detach();
var swiping;
var height = 0;
var start_x = 0;
var edge = 20;
var swipe_min = 60;
document.addEventListener('touchstart', (event) => {
if (event.changedTouches.length == 1) {
var touch = event.changedTouches[0];
height = touch.clientY;
start_x = touch.clientX;
if (touch.clientX < edge) {
swiping = 'left';
} else if (document.body.clientWidth - touch.clientX < edge) {
swiping = 'right';
}
}
}, false)
document.addEventListener('touchend', (event) => {
if (event.changedTouches.length == 1) {
var touch = event.changedTouches[0];
var delta_height = Math.abs(height - touch.clientY);
if (start_x < edge && touch.clientX > swipe_min && delta_height < 30) {
if (page_wrapper.hasClass('show_right')) {
BarItems.sidebar_right.trigger(event);
} else {
BarItems.sidebar_left.trigger(event);
}
} else if (
document.body.clientWidth - start_x < edge &&
(document.body.clientWidth - touch.clientX) > swipe_min &&
delta_height < 30
) {
if (page_wrapper.hasClass('show_left')) {
BarItems.sidebar_left.trigger(event);
} else {
BarItems.sidebar_right.trigger(event);
}
} else if (
document.body.clientWidth - start_x < 40 &&
document.body.clientWidth - touch.clientX < 40 &&
delta_height < 10 &&
event.target == page_wrapper[0] &&
(page_wrapper.hasClass('show_left') || page_wrapper.hasClass('show_right'))
) {
page_wrapper.removeClass('show_left')
page_wrapper.removeClass('show_right')
BarItems.sidebar_left.nodes.forEach(n => {
$(n).removeClass('sel')
Interface.PanelSelectorVue = new Vue({
el: '#panel_selector_bar',
data: {
all_panels: Interface.Panels,
selected: null,
},
computed: {
panels() {
let arr = [];
arr.push({
icon: '3d_rotation',
name: tl('data.preview'),
id: 'preview'
})
updateInterfacePanels()
resizeWindow()
for (var id in this.all_panels) {
let panel = this.all_panels[id];
if (Condition(panel.condition)) {
console.log(id)
arr.push(panel)
}
}
return arr;
}
},
methods: {
select(panel) {
this.selected = panel && panel.id;
let overlay = $('#mobile_panel_overlay');
$('#left_bar').append(overlay.children());
if (panel instanceof Panel) {
overlay.append(panel.node);
if (panel.onResize) panel.onResize();
overlay.show();
} else {
overlay.hide();
}
}
}
height = 0;
swiping = undefined;
}, false)
})
}
})
}