nixos-configs/modules/ags/config/ts/media-player/gesture.ts

172 lines
5.6 KiB
TypeScript
Raw Normal View History

import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
import { Box, EventBox, Overlay } from 'resource:///com/github/Aylur/ags/widget.js';
const { Gtk } = imports.gi;
const MAX_OFFSET = 200;
const OFFSCREEN = 500;
const ANIM_DURATION = 500;
const TRANSITION = `transition: margin ${ANIM_DURATION}ms ease,
opacity ${ANIM_DURATION}ms ease;`;
2024-01-13 11:15:08 -05:00
// Types
import AgsOverlay from 'types/widgets/overlay';
import OverlayProps from 'types/widgets/overlay';
import AgsBox from 'types/widgets/box';
import AgsCenterBox from 'types/widgets/centerbox';
import { Connectable } from 'types/widgets/widget';
type Gesture = {
attribute?: Object
setup?(self: Connectable<AgsOverlay> & AgsOverlay): void
props?: OverlayProps
};
2023-12-20 17:14:07 -05:00
export default ({
2023-12-18 18:00:30 -05:00
attribute = {},
setup = () => {/**/},
2023-12-18 18:00:30 -05:00
...props
2024-01-13 11:15:08 -05:00
}: Gesture) => {
const widget = EventBox();
const gesture = Gtk.GestureDrag.new(widget);
// Have empty PlayerBox to define the size of the widget
2023-12-18 18:00:30 -05:00
const emptyPlayer = Box({
class_name: 'player',
attribute: { empty: true },
});
const content = Overlay({
...props,
2023-12-18 18:00:30 -05:00
attribute: {
...attribute,
dragging: false,
2024-01-13 11:15:08 -05:00
includesWidget: (playerW: AgsOverlay) => {
return content.overlays.find((w) => w === playerW);
2023-12-18 18:00:30 -05:00
},
2024-01-13 11:15:08 -05:00
showTopOnly: () => content.overlays.forEach((over) => {
over.visible = over === content.overlays.at(-1);
}),
2023-12-18 18:00:30 -05:00
2024-01-13 11:15:08 -05:00
moveToTop: (player: AgsCenterBox) => {
2023-12-18 18:00:30 -05:00
player.visible = true;
content.reorder_overlay(player, -1);
timeout(ANIM_DURATION, () => {
content.attribute.showTopOnly();
});
},
},
child: emptyPlayer,
setup: (self) => {
setup(self);
self
2023-12-23 01:14:21 -05:00
.hook(gesture, (_, realGesture) => {
if (realGesture) {
2024-01-13 11:15:08 -05:00
self.overlays.forEach((over) => {
over.visible = true;
});
2023-12-23 01:14:21 -05:00
}
else {
self.attribute.showTopOnly();
}
// Don't allow gesture when only one player
2024-01-13 11:15:08 -05:00
if (self.overlays.length <= 1) {
2023-12-23 01:14:21 -05:00
return;
}
self.attribute.dragging = true;
let offset = gesture.get_offset()[1];
2024-01-13 11:15:08 -05:00
const playerBox = self.overlays.at(-1) as AgsBox;
2023-12-23 01:14:21 -05:00
if (!offset) {
return;
}
// Slide right
if (offset >= 0) {
playerBox.setCss(`
margin-left: ${offset}px;
margin-right: -${offset}px;
2023-12-18 18:00:30 -05:00
${playerBox.attribute.bgStyle}
`);
2023-12-23 01:14:21 -05:00
}
2023-12-23 01:14:21 -05:00
// Slide left
else {
offset = Math.abs(offset);
playerBox.setCss(`
margin-left: -${offset}px;
margin-right: ${offset}px;
2023-12-18 18:00:30 -05:00
${playerBox.attribute.bgStyle}
`);
2023-12-23 01:14:21 -05:00
}
}, 'drag-update')
2023-12-23 01:14:21 -05:00
.hook(gesture, () => {
// Don't allow gesture when only one player
2024-01-13 11:15:08 -05:00
if (self.overlays.length <= 1) {
2023-12-23 01:14:21 -05:00
return;
}
2023-12-23 01:14:21 -05:00
self.attribute.dragging = false;
const offset = gesture.get_offset()[1];
2024-01-13 11:15:08 -05:00
const playerBox = self.overlays.at(-1) as AgsBox;
2023-12-23 01:14:21 -05:00
// If crosses threshold after letting go, slide away
if (offset && Math.abs(offset) > MAX_OFFSET) {
// Disable inputs during animation
widget.sensitive = false;
2023-12-23 01:14:21 -05:00
// Slide away right
if (offset >= 0) {
playerBox.setCss(`
${TRANSITION}
margin-left: ${OFFSCREEN}px;
margin-right: -${OFFSCREEN}px;
2023-12-18 18:00:30 -05:00
opacity: 0.7; ${playerBox.attribute.bgStyle}
`);
2023-12-23 01:14:21 -05:00
}
2023-12-23 01:14:21 -05:00
// Slide away left
else {
playerBox.setCss(`
${TRANSITION}
margin-left: -${OFFSCREEN}px;
margin-right: ${OFFSCREEN}px;
2023-12-18 18:00:30 -05:00
opacity: 0.7; ${playerBox.attribute.bgStyle}
`);
2023-12-23 01:14:21 -05:00
}
2023-12-23 01:14:21 -05:00
timeout(ANIM_DURATION, () => {
// Put the player in the back after anim
self.reorder_overlay(playerBox, 0);
// Recenter player
playerBox.setCss(playerBox.attribute.bgStyle);
2023-12-23 01:14:21 -05:00
widget.sensitive = true;
2023-12-23 01:14:21 -05:00
self.attribute.showTopOnly();
});
}
else {
// Recenter with transition for animation
playerBox.setCss(`${TRANSITION}
2023-12-18 18:00:30 -05:00
${playerBox.attribute.bgStyle}`);
2023-12-23 01:14:21 -05:00
}
}, 'drag-end');
},
});
widget.add(content);
return widget;
};