Merge pull request #4326 from itsjohncs/mobile-channel-list-sorting
Allow network list reordering via touch.
This commit is contained in:
commit
fcffab1259
@ -82,11 +82,15 @@ export default {
|
|||||||
this.$root.switchToChannel(this.channel);
|
this.$root.switchToChannel(this.channel);
|
||||||
},
|
},
|
||||||
openContextMenu(event) {
|
openContextMenu(event) {
|
||||||
eventbus.emit("contextmenu:channel", {
|
// events.buttons will be 0 when the event is caused by a long
|
||||||
event: event,
|
// touch on Android.
|
||||||
channel: this.channel,
|
if (event.buttons !== 0) {
|
||||||
network: this.network,
|
eventbus.emit("contextmenu:channel", {
|
||||||
});
|
event: event,
|
||||||
|
channel: this.channel,
|
||||||
|
network: this.network,
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -56,17 +56,18 @@
|
|||||||
<Draggable
|
<Draggable
|
||||||
v-else
|
v-else
|
||||||
:list="$store.state.networks"
|
:list="$store.state.networks"
|
||||||
:filter="isCurrentlyInTouch"
|
:delay="LONG_TOUCH_DURATION"
|
||||||
:prevent-on-filter="false"
|
:delay-on-touch-only="true"
|
||||||
|
:touch-start-threshold="10"
|
||||||
handle=".channel-list-item[data-type='lobby']"
|
handle=".channel-list-item[data-type='lobby']"
|
||||||
draggable=".network"
|
draggable=".network"
|
||||||
ghost-class="ui-sortable-ghost"
|
ghost-class="ui-sortable-ghost"
|
||||||
drag-class="ui-sortable-dragged"
|
drag-class="ui-sortable-dragging"
|
||||||
group="networks"
|
group="networks"
|
||||||
class="networks"
|
class="networks"
|
||||||
@change="onNetworkSort"
|
@change="onNetworkSort"
|
||||||
@start="onDragStart"
|
@choose="onDraggableChoose"
|
||||||
@end="onDragEnd"
|
@unchoose="onDraggableUnchoose"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="network in $store.state.networks"
|
v-for="network in $store.state.networks"
|
||||||
@ -80,6 +81,9 @@
|
|||||||
class="network"
|
class="network"
|
||||||
role="region"
|
role="region"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
|
@touchstart="onDraggableTouchStart"
|
||||||
|
@touchend="onDraggableTouchEnd"
|
||||||
|
@touchcancel="onDraggableTouchEnd"
|
||||||
>
|
>
|
||||||
<NetworkLobby
|
<NetworkLobby
|
||||||
:network="network"
|
:network="network"
|
||||||
@ -100,15 +104,16 @@
|
|||||||
<Draggable
|
<Draggable
|
||||||
draggable=".channel-list-item"
|
draggable=".channel-list-item"
|
||||||
ghost-class="ui-sortable-ghost"
|
ghost-class="ui-sortable-ghost"
|
||||||
drag-class="ui-sortable-dragged"
|
drag-class="ui-sortable-dragging"
|
||||||
:group="network.uuid"
|
:group="network.uuid"
|
||||||
:filter="isCurrentlyInTouch"
|
|
||||||
:prevent-on-filter="false"
|
|
||||||
:list="network.channels"
|
:list="network.channels"
|
||||||
|
:delay="LONG_TOUCH_DURATION"
|
||||||
|
:delay-on-touch-only="true"
|
||||||
|
:touch-start-threshold="10"
|
||||||
class="channels"
|
class="channels"
|
||||||
@change="onChannelSort"
|
@change="onChannelSort"
|
||||||
@start="onDragStart"
|
@choose="onDraggableChoose"
|
||||||
@end="onDragEnd"
|
@unchoose="onDraggableUnchoose"
|
||||||
>
|
>
|
||||||
<template v-for="(channel, index) in network.channels">
|
<template v-for="(channel, index) in network.channels">
|
||||||
<Channel
|
<Channel
|
||||||
@ -247,6 +252,10 @@ export default {
|
|||||||
this.setActiveSearchItem();
|
this.setActiveSearchItem();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
// Number of milliseconds a touch has to last to be considered long
|
||||||
|
this.LONG_TOUCH_DURATION = 500;
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
Mousetrap.bind("alt+shift+right", this.expandNetwork);
|
Mousetrap.bind("alt+shift+right", this.expandNetwork);
|
||||||
Mousetrap.bind("alt+shift+left", this.collapseNetwork);
|
Mousetrap.bind("alt+shift+left", this.collapseNetwork);
|
||||||
@ -280,16 +289,6 @@ export default {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
isCurrentlyInTouch(e) {
|
|
||||||
// TODO: Implement a way to sort on touch devices
|
|
||||||
return e.pointerType !== "mouse";
|
|
||||||
},
|
|
||||||
onDragStart(e) {
|
|
||||||
e.target.classList.add("ui-sortable-active");
|
|
||||||
},
|
|
||||||
onDragEnd(e) {
|
|
||||||
e.target.classList.remove("ui-sortable-active");
|
|
||||||
},
|
|
||||||
onNetworkSort(e) {
|
onNetworkSort(e) {
|
||||||
if (!e.moved) {
|
if (!e.moved) {
|
||||||
return;
|
return;
|
||||||
@ -317,6 +316,38 @@ export default {
|
|||||||
order: channel.network.channels.map((c) => c.id),
|
order: channel.network.channels.map((c) => c.id),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
isTouchEvent(event) {
|
||||||
|
// This is the same way Sortable.js detects a touch event. See
|
||||||
|
// SortableJS/Sortable@daaefeda:/src/Sortable.js#L465
|
||||||
|
return (
|
||||||
|
(event.touches && event.touches[0]) ||
|
||||||
|
(event.pointerType && event.pointerType === "touch")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onDraggableChoose(event) {
|
||||||
|
if (this.isTouchEvent(event.originalEvent)) {
|
||||||
|
// onDrag is only triggered when the user actually moves the
|
||||||
|
// dragged object but onChoose is triggered as soon as the
|
||||||
|
// item is eligible for dragging. This gives us an opportunity
|
||||||
|
// to tell the user they've held the touch long enough.
|
||||||
|
event.item.classList.add("ui-sortable-dragging-touch-cue");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDraggableUnchoose(event) {
|
||||||
|
event.item.classList.remove("ui-sortable-dragging-touch-cue");
|
||||||
|
},
|
||||||
|
onDraggableTouchStart() {
|
||||||
|
if (event.touches.length === 1) {
|
||||||
|
// This prevents an iOS long touch default behavior: selecting
|
||||||
|
// the nearest selectable text.
|
||||||
|
document.body.classList.add("force-no-select");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDraggableTouchEnd(event) {
|
||||||
|
if (event.touches.length === 0) {
|
||||||
|
document.body.classList.remove("force-no-select");
|
||||||
|
}
|
||||||
|
},
|
||||||
toggleSearch(event) {
|
toggleSearch(event) {
|
||||||
if (isIgnoredKeybind(event)) {
|
if (isIgnoredKeybind(event)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -107,6 +107,10 @@ body {
|
|||||||
overflow: hidden; /* iOS Safari requires overflow rather than overflow-y */
|
overflow: hidden; /* iOS Safari requires overflow rather than overflow-y */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.force-no-select * {
|
||||||
|
user-select: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
a,
|
a,
|
||||||
a:hover,
|
a:hover,
|
||||||
a:focus {
|
a:focus {
|
||||||
@ -707,14 +711,19 @@ background on hover (unless active) */
|
|||||||
|
|
||||||
/* Remove background on hovered/active channel when sorting/drag-and-dropping */
|
/* Remove background on hovered/active channel when sorting/drag-and-dropping */
|
||||||
.ui-sortable-ghost,
|
.ui-sortable-ghost,
|
||||||
.channel-list-item.ui-sortable-dragged,
|
.ui-sortable-dragging .channel-list-item,
|
||||||
.ui-sortable-dragged .channel-list-item,
|
.ui-sortable-dragging,
|
||||||
.ui-sortable-active .channel-list-item:hover,
|
.ui-sortable-dragging:hover,
|
||||||
.ui-sortable-active .channel-list-item.active {
|
.ui-sortable-dragging.active,
|
||||||
|
.ui-sortable-dragging-touch-cue .channel-list-item,
|
||||||
|
.ui-sortable-dragging-touch-cue,
|
||||||
|
.ui-sortable-dragging-touch-cue:hover,
|
||||||
|
.ui-sortable-dragging-touch-cue.active {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-sortable-ghost::after {
|
.ui-sortable-ghost::after,
|
||||||
|
.ui-sortable-dragging-touch-cue:not(.ui-sortable-dragging)::after {
|
||||||
background: var(--body-bg-color);
|
background: var(--body-bg-color);
|
||||||
border: 1px dashed #99a2b4;
|
border: 1px dashed #99a2b4;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@ -727,6 +736,10 @@ background on hover (unless active) */
|
|||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-sortable-dragging-touch-cue:not(.ui-sortable-ghost)::after {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
#sidebar .network {
|
#sidebar .network {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
Loading…
Reference in New Issue
Block a user