feat(media-player): add full dragging gesture
This commit is contained in:
parent
53275e6372
commit
28881bd2dd
3 changed files with 137 additions and 78 deletions
82
config/ags/js/media-player/gesture.js
Normal file
82
config/ags/js/media-player/gesture.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
const { Box, Overlay, EventBox } = ags.Widget;
|
||||||
|
const { Gtk } = imports.gi;
|
||||||
|
|
||||||
|
const MAX_OFFSET = 200;
|
||||||
|
const OFFSCREEN = 500;
|
||||||
|
const TRANSITION = 'transition: margin 0.5s ease, opacity 3s ease;';
|
||||||
|
|
||||||
|
export default ({ properties, connections, params } = {}) => {
|
||||||
|
let widget = EventBox();
|
||||||
|
|
||||||
|
let gesture = Gtk.GestureDrag.new(widget)
|
||||||
|
|
||||||
|
widget.child = Overlay({
|
||||||
|
...params,
|
||||||
|
properties: [
|
||||||
|
...properties,
|
||||||
|
['dragging', false],
|
||||||
|
],
|
||||||
|
child: Box({className: 'player'}),
|
||||||
|
connections: [
|
||||||
|
...connections,
|
||||||
|
|
||||||
|
[gesture, overlay => {
|
||||||
|
if (overlay.overlays.length <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
overlay._dragging = true;
|
||||||
|
const offset = gesture.get_offset()[1];
|
||||||
|
|
||||||
|
let playerBox = overlay.get_children().at(-1);
|
||||||
|
if (offset >= 0) {
|
||||||
|
playerBox.setStyle(`margin-left: ${offset}px;
|
||||||
|
margin-right: -${offset}px;
|
||||||
|
${playerBox._bgStyle}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let newOffset = Math.abs(offset);
|
||||||
|
playerBox.setStyle(`margin-left: -${newOffset}px;
|
||||||
|
margin-right: ${newOffset}px;
|
||||||
|
${playerBox._bgStyle}`);
|
||||||
|
}
|
||||||
|
overlay._selected = playerBox;
|
||||||
|
}, 'drag-update'],
|
||||||
|
|
||||||
|
[gesture, overlay => {
|
||||||
|
if (overlay.overlays.length <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
overlay._dragging = false;
|
||||||
|
const offset = gesture.get_offset()[1];
|
||||||
|
|
||||||
|
let playerBox = overlay.get_children().at(-1);
|
||||||
|
|
||||||
|
if (Math.abs(offset) > MAX_OFFSET) {
|
||||||
|
if (offset >= 0) {
|
||||||
|
playerBox.setStyle(`${TRANSITION}
|
||||||
|
margin-left: ${OFFSCREEN}px;
|
||||||
|
margin-right: -${OFFSCREEN}px;
|
||||||
|
opacity: 0;
|
||||||
|
${playerBox._bgStyle}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
playerBox.setStyle(`${TRANSITION}
|
||||||
|
margin-left: -${OFFSCREEN}px;
|
||||||
|
margin-right: ${OFFSCREEN}px;
|
||||||
|
opacity: 0;
|
||||||
|
${playerBox._bgStyle}`);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
overlay.reorder_overlay(playerBox, 0);
|
||||||
|
playerBox.setStyle(playerBox._bgStyle);
|
||||||
|
overlay._selected = overlay.get_children().at(-1);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
playerBox.setStyle(`${TRANSITION} ${playerBox._bgStyle}`);
|
||||||
|
|
||||||
|
}, 'drag-end'],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return widget;
|
||||||
|
};
|
|
@ -29,6 +29,7 @@ export const CoverArt = (player, params) => CenterBox({
|
||||||
...params,
|
...params,
|
||||||
className: 'player',
|
className: 'player',
|
||||||
vertical: true,
|
vertical: true,
|
||||||
|
properties: [['bgStyle', '']],
|
||||||
connections: [
|
connections: [
|
||||||
[player, box => {
|
[player, box => {
|
||||||
execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && coloryou "${player.coverPath}"`])
|
execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && coloryou "${player.coverPath}"`])
|
||||||
|
@ -36,12 +37,14 @@ export const CoverArt = (player, params) => CenterBox({
|
||||||
if (box) {
|
if (box) {
|
||||||
player.colors.value = JSON.parse(out);
|
player.colors.value = JSON.parse(out);
|
||||||
|
|
||||||
box.setStyle(`background: radial-gradient(circle,
|
box._bgStyle = `background: radial-gradient(circle,
|
||||||
rgba(0, 0, 0, 0.4) 30%,
|
rgba(0, 0, 0, 0.4) 30%,
|
||||||
${player.colors.value.imageAccent}),
|
${player.colors.value.imageAccent}),
|
||||||
url("${player.coverPath}");
|
url("${player.coverPath}");
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;`);
|
background-position: center;`;
|
||||||
|
if (!box.get_parent()._dragging)
|
||||||
|
box.setStyle(box._bgStyle);
|
||||||
}
|
}
|
||||||
}).catch(err => { if (err !== "") print(err) });
|
}).catch(err => { if (err !== "") print(err) });
|
||||||
}],
|
}],
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const { Mpris } = ags.Service;
|
const { Mpris } = ags.Service;
|
||||||
const { Box, CenterBox, Label, Stack, EventBox } = ags.Widget;
|
const { Box, CenterBox, Label } = ags.Widget;
|
||||||
const { Gtk } = imports.gi;
|
|
||||||
|
|
||||||
import * as mpris from './mpris.js';
|
import * as mpris from './mpris.js';
|
||||||
|
import PlayerGesture from './gesture.js';
|
||||||
import { Separator } from '../misc/separator.js';
|
import { Separator } from '../misc/separator.js';
|
||||||
|
|
||||||
const Top = player => Box({
|
const Top = player => Box({
|
||||||
|
@ -56,7 +56,7 @@ const Center = player => Box({
|
||||||
const Bottom = player => Box({
|
const Bottom = player => Box({
|
||||||
className: 'bottom',
|
className: 'bottom',
|
||||||
children: [
|
children: [
|
||||||
|
|
||||||
mpris.PreviousButton(player, {
|
mpris.PreviousButton(player, {
|
||||||
valign: 'end',
|
valign: 'end',
|
||||||
halign: 'start',
|
halign: 'start',
|
||||||
|
@ -83,81 +83,55 @@ const PlayerBox = player => mpris.CoverArt(player, {
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default () => {
|
export default () => PlayerGesture({
|
||||||
let widget = EventBox();
|
className: 'media',
|
||||||
|
properties: [
|
||||||
|
['players', new Map()],
|
||||||
|
['setup', false],
|
||||||
|
['selected'],
|
||||||
|
],
|
||||||
|
connections: [
|
||||||
|
[Mpris, (overlay, busName) => {
|
||||||
|
if (!busName || overlay._players.has(busName))
|
||||||
|
return;
|
||||||
|
|
||||||
let gesture = Gtk.GestureDrag.new(widget)
|
const player = Mpris.getPlayer(busName);
|
||||||
|
player.colors = ags.Variable();
|
||||||
|
overlay._players.set(busName, PlayerBox(player));
|
||||||
|
|
||||||
widget.child = Stack({
|
let result = [];
|
||||||
className: 'media',
|
overlay._players.forEach(widget => {
|
||||||
properties: [
|
result.push(widget);
|
||||||
['players', new Map()],
|
});
|
||||||
['previous', 'spotify'],
|
|
||||||
],
|
|
||||||
connections: [
|
|
||||||
[gesture, stack => {
|
|
||||||
const offset = gesture.get_offset()[1];
|
|
||||||
if (Math.abs(offset) > 200) {
|
|
||||||
let players = [];
|
|
||||||
stack._players.forEach((_, busName) => players.push(Mpris.getPlayer(busName).name));
|
|
||||||
let current = players.findIndex(player => player === stack.shown);
|
|
||||||
|
|
||||||
if (offset > 0) {
|
overlay.overlays = result;
|
||||||
stack.transition = 'slide_right';
|
|
||||||
if (players[++current])
|
// Favor spotify
|
||||||
stack.shown = `${players[current]}`;
|
if (!overlay._setup) {
|
||||||
else
|
if (overlay._players.has('org.mpris.MediaPlayer2.spotify')) {
|
||||||
stack.shown = `${players[0]}`;
|
overlay._selected = overlay._players.get('org.mpris.MediaPlayer2.spotify');
|
||||||
}
|
|
||||||
else {
|
|
||||||
stack.transition = 'slide_left';
|
|
||||||
if (players[--current])
|
|
||||||
stack.shown = `${players[current]}`;
|
|
||||||
else
|
|
||||||
stack.shown = `${players.at(-1)}`;
|
|
||||||
}
|
|
||||||
stack._previous = stack.shown;
|
|
||||||
}
|
}
|
||||||
}, 'drag-end'],
|
overlay._setup = true;
|
||||||
|
}
|
||||||
|
|
||||||
[Mpris, (stack, busName) => {
|
if (overlay._selected)
|
||||||
if (!busName || stack._players.has(busName))
|
overlay.reorder_overlay(overlay._selected, -1);
|
||||||
return;
|
}, 'player-added'],
|
||||||
|
|
||||||
const player = Mpris.getPlayer(busName);
|
[Mpris, (overlay, busName) => {
|
||||||
player.colors = ags.Variable();
|
if (!busName || !overlay._players.has(busName))
|
||||||
stack._players.set(busName, PlayerBox(player));
|
return;
|
||||||
|
|
||||||
let result = [];
|
overlay._players.delete(busName);
|
||||||
stack._players.forEach((widget, busName) => {
|
|
||||||
result.push([`${Mpris.getPlayer(busName).name}`, widget]);
|
|
||||||
});
|
|
||||||
|
|
||||||
stack.items = result;
|
let result = [];
|
||||||
if (result.find(p => p[0] === stack._previous))
|
overlay._players.forEach(widget => {
|
||||||
stack.shown = stack._previous;
|
result.push(widget);
|
||||||
else if (stack._players.has('org.mpris.MediaPlayer2.spotify'))
|
});
|
||||||
stack.shown = `spotify`;
|
|
||||||
}, 'player-added'],
|
|
||||||
|
|
||||||
[Mpris, (stack, busName) => {
|
overlay.overlays = result;
|
||||||
if (!busName || !stack._players.has(busName))
|
if (overlay._selected)
|
||||||
return;
|
overlay.reorder_overlay(overlay._selected, -1);
|
||||||
|
}, 'player-closed'],
|
||||||
stack._players.delete(busName);
|
],
|
||||||
|
})
|
||||||
let result = [];
|
|
||||||
stack._players.forEach((widget, busName) => {
|
|
||||||
result.push([`${Mpris.getPlayer(busName).name}`, widget]);
|
|
||||||
});
|
|
||||||
|
|
||||||
stack.items = result;
|
|
||||||
if (result.find(p => p[0] === stack._previous))
|
|
||||||
stack.shown = stack._previous;
|
|
||||||
else if (stack._players.has('org.mpris.MediaPlayer2.spotify'))
|
|
||||||
stack.shown = `spotify`;
|
|
||||||
}, 'player-closed'],
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return widget;
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in a new issue