From 28881bd2dd3ca9f294543b6379443829787d36ec Mon Sep 17 00:00:00 2001 From: matt1432 Date: Tue, 26 Sep 2023 10:43:37 -0400 Subject: [PATCH] feat(media-player): add full dragging gesture --- config/ags/js/media-player/gesture.js | 82 ++++++++++++++++++ config/ags/js/media-player/mpris.js | 15 ++-- config/ags/js/media-player/player.js | 118 ++++++++++---------------- 3 files changed, 137 insertions(+), 78 deletions(-) create mode 100644 config/ags/js/media-player/gesture.js diff --git a/config/ags/js/media-player/gesture.js b/config/ags/js/media-player/gesture.js new file mode 100644 index 0000000..b2798e2 --- /dev/null +++ b/config/ags/js/media-player/gesture.js @@ -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; +}; diff --git a/config/ags/js/media-player/mpris.js b/config/ags/js/media-player/mpris.js index 575d836..a042343 100644 --- a/config/ags/js/media-player/mpris.js +++ b/config/ags/js/media-player/mpris.js @@ -29,6 +29,7 @@ export const CoverArt = (player, params) => CenterBox({ ...params, className: 'player', vertical: true, + properties: [['bgStyle', '']], connections: [ [player, box => { execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && coloryou "${player.coverPath}"`]) @@ -36,12 +37,14 @@ export const CoverArt = (player, params) => CenterBox({ if (box) { player.colors.value = JSON.parse(out); - box.setStyle(`background: radial-gradient(circle, - rgba(0, 0, 0, 0.4) 30%, - ${player.colors.value.imageAccent}), - url("${player.coverPath}"); - background-size: cover; - background-position: center;`); + box._bgStyle = `background: radial-gradient(circle, + rgba(0, 0, 0, 0.4) 30%, + ${player.colors.value.imageAccent}), + url("${player.coverPath}"); + background-size: cover; + background-position: center;`; + if (!box.get_parent()._dragging) + box.setStyle(box._bgStyle); } }).catch(err => { if (err !== "") print(err) }); }], diff --git a/config/ags/js/media-player/player.js b/config/ags/js/media-player/player.js index 0afe7f0..c31d87a 100644 --- a/config/ags/js/media-player/player.js +++ b/config/ags/js/media-player/player.js @@ -1,8 +1,8 @@ const { Mpris } = ags.Service; -const { Box, CenterBox, Label, Stack, EventBox } = ags.Widget; -const { Gtk } = imports.gi; +const { Box, CenterBox, Label } = ags.Widget; import * as mpris from './mpris.js'; +import PlayerGesture from './gesture.js'; import { Separator } from '../misc/separator.js'; const Top = player => Box({ @@ -56,7 +56,7 @@ const Center = player => Box({ const Bottom = player => Box({ className: 'bottom', children: [ - + mpris.PreviousButton(player, { valign: 'end', halign: 'start', @@ -83,81 +83,55 @@ const PlayerBox = player => mpris.CoverArt(player, { ], }); -export default () => { - let widget = EventBox(); +export default () => PlayerGesture({ + 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({ - className: 'media', - properties: [ - ['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); + let result = []; + overlay._players.forEach(widget => { + result.push(widget); + }); - if (offset > 0) { - stack.transition = 'slide_right'; - if (players[++current]) - stack.shown = `${players[current]}`; - else - stack.shown = `${players[0]}`; - } - else { - stack.transition = 'slide_left'; - if (players[--current]) - stack.shown = `${players[current]}`; - else - stack.shown = `${players.at(-1)}`; - } - stack._previous = stack.shown; + overlay.overlays = result; + + // Favor spotify + if (!overlay._setup) { + if (overlay._players.has('org.mpris.MediaPlayer2.spotify')) { + overlay._selected = overlay._players.get('org.mpris.MediaPlayer2.spotify'); } - }, 'drag-end'], + overlay._setup = true; + } - [Mpris, (stack, busName) => { - if (!busName || stack._players.has(busName)) - return; + if (overlay._selected) + overlay.reorder_overlay(overlay._selected, -1); + }, 'player-added'], - const player = Mpris.getPlayer(busName); - player.colors = ags.Variable(); - stack._players.set(busName, PlayerBox(player)); + [Mpris, (overlay, busName) => { + if (!busName || !overlay._players.has(busName)) + return; - let result = []; - stack._players.forEach((widget, busName) => { - result.push([`${Mpris.getPlayer(busName).name}`, widget]); - }); + overlay._players.delete(busName); - 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-added'], + let result = []; + overlay._players.forEach(widget => { + result.push(widget); + }); - [Mpris, (stack, busName) => { - if (!busName || !stack._players.has(busName)) - return; - - 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; -}; + overlay.overlays = result; + if (overlay._selected) + overlay.reorder_overlay(overlay._selected, -1); + }, 'player-closed'], + ], +})