From 333b9d8224f00a3f198292dabafaf0cd3d40e7ad Mon Sep 17 00:00:00 2001 From: Rafostar <40623528+Rafostar@users.noreply.github.com> Date: Wed, 2 Dec 2020 10:59:02 +0100 Subject: [PATCH] Mobile friendly interface transitions #14 --- clapper_src/buttons.js | 7 +++- clapper_src/controls.js | 84 +++++++++++++++++++++++++++++++++------- clapper_src/revealers.js | 71 +++++++++++++++++++++++++++++++++ css/styles.css | 14 +++++++ 4 files changed, 159 insertions(+), 17 deletions(-) diff --git a/clapper_src/buttons.js b/clapper_src/buttons.js index 5e66811f..6672e5f9 100644 --- a/clapper_src/buttons.js +++ b/clapper_src/buttons.js @@ -10,8 +10,8 @@ class ClapperCustomButton extends Gtk.Button let defaults = { margin_top: 4, margin_bottom: 4, - margin_start: 1, - margin_end: 1, + margin_start: 2, + margin_end: 2, }; Object.assign(opts, defaults); @@ -31,6 +31,9 @@ class ClapperCustomButton extends Gtk.Button return; this.margin_top = (isFullscreen) ? 6 : 4; + this.margin_start = (isFullscreen) ? 3 : 2; + this.margin_end = (isFullscreen) ? 3 : 2; + this.isFullscreen = isFullscreen; } diff --git a/clapper_src/controls.js b/clapper_src/controls.js index 20261f48..70ef3f76 100644 --- a/clapper_src/controls.js +++ b/clapper_src/controls.js @@ -2,9 +2,10 @@ const { GObject, Gdk, Gtk } = imports.gi; const Buttons = imports.clapper_src.buttons; const Debug = imports.clapper_src.debug; const Misc = imports.clapper_src.misc; +const Revealers = imports.clapper_src.revealers; -const CONTROLS_MARGIN = 4; -const CONTROLS_SPACING = 4; +const CONTROLS_MARGIN = 3; +const CONTROLS_SPACING = 0; let { debug } = Debug; let { settings } = Misc; @@ -27,39 +28,69 @@ class ClapperControls extends Gtk.Box this.currentPosition = 0; this.currentDuration = 0; this.isPositionDragging = false; + this.isMobile = false; this.showHours = false; this.durationFormatted = '00:00'; this.buttonsArr = []; + this.revealersArr = []; this._addTogglePlayButton(); - this.elapsedButton = this.addLabelButton('00:00/00:00'); + + let elapsedRevealer = new Revealers.ButtonsRevealer('SLIDE_RIGHT'); + this.elapsedButton = this.addLabelButton('00:00/00:00', elapsedRevealer); + elapsedRevealer.set_reveal_child(true); + this.revealersArr.push(elapsedRevealer); + this.append(elapsedRevealer); + this._addPositionScale(); + + let revealTracksButton = new Buttons.IconToggleButton( + 'go-previous-symbolic', + 'go-next-symbolic' + ); + revealTracksButton.floatUnaffected = false; + revealTracksButton.add_css_class('narrowbutton'); + this.buttonsArr.push(revealTracksButton); + let tracksRevealer = new Revealers.ButtonsRevealer('SLIDE_LEFT', revealTracksButton); this.visualizationsButton = this.addPopoverButton( - 'display-projector-symbolic' + 'display-projector-symbolic', + tracksRevealer ); this.visualizationsButton.set_visible(false); this.videoTracksButton = this.addPopoverButton( - 'emblem-videos-symbolic' + 'emblem-videos-symbolic', + tracksRevealer ); this.videoTracksButton.set_visible(false); this.audioTracksButton = this.addPopoverButton( - 'emblem-music-symbolic' + 'emblem-music-symbolic', + tracksRevealer ); this.audioTracksButton.set_visible(false); this.subtitleTracksButton = this.addPopoverButton( - 'media-view-subtitles-symbolic' + 'media-view-subtitles-symbolic', + tracksRevealer ); this.subtitleTracksButton.set_visible(false); + + this.revealTracksRevealer = new Revealers.ButtonsRevealer('SLIDE_LEFT'); + this.revealTracksRevealer.append(revealTracksButton); + this.append(this.revealTracksRevealer); + + tracksRevealer.set_reveal_child(true); + this.revealersArr.push(tracksRevealer); + this.append(tracksRevealer); + this._addVolumeButton(); this.unfullscreenButton = this.addButton( - 'view-restore-symbolic', + 'view-restore-symbolic' ); this.unfullscreenButton.connect('clicked', this._onUnfullscreenClicked.bind(this)); this.unfullscreenButton.set_visible(false); this.unfloatButton = this.addButton( - 'preferences-desktop-remote-desktop-symbolic', + 'preferences-desktop-remote-desktop-symbolic' ); this.unfloatButton.connect('clicked', this._onUnfloatClicked.bind(this)); this.unfloatButton.set_visible(false); @@ -75,6 +106,9 @@ class ClapperControls extends Gtk.Box setFullscreenMode(isFullscreen) { + /* Allow recheck on next resize */ + this.isMobile = null; + for(let button of this.buttonsArr) button.setFullscreenMode(isFullscreen); @@ -84,6 +118,8 @@ class ClapperControls extends Gtk.Box setFloatingMode(isFloating) { + this.isMobile = null; + for(let button of this.buttonsArr) button.setFloatingMode(isFloating); } @@ -106,31 +142,35 @@ class ClapperControls extends Gtk.Box this.elapsedButton.set_label(elapsed); } - addButton(buttonIcon) + addButton(buttonIcon, revealer) { let button = (buttonIcon instanceof Gtk.Button) ? buttonIcon : new Buttons.IconButton(buttonIcon); - this.append(button); + if(!revealer) + this.append(button); + else + revealer.append(button); + this.buttonsArr.push(button); return button; } - addLabelButton(text) + addLabelButton(text, revealer) { text = text || ''; let button = new Buttons.LabelButton(text); - return this.addButton(button); + return this.addButton(button, revealer); } - addPopoverButton(iconName) + addPopoverButton(iconName, revealer) { let button = new Buttons.PopoverButton(iconName); - return this.addButton(button); + return this.addButton(button, revealer); } addCheckButtons(box, array, activeId) @@ -374,6 +414,20 @@ class ClapperControls extends Gtk.Box : Misc.getCubicValue(settings.get_double('volume-last')); this.volumeScale.set_value(initialVolume); + player.widget.connect('resize', this._onPlayerResize.bind(this)); + } + + _onPlayerResize(widget, width, height) + { + let isMobile = (width < 560); + if(this.isMobile === isMobile) + return; + + for(let revealer of this.revealersArr) + revealer.set_reveal_child(!isMobile); + + this.revealTracksRevealer.set_reveal_child(isMobile); + this.isMobile = isMobile; } _onUnfullscreenClicked(button) diff --git a/clapper_src/revealers.js b/clapper_src/revealers.js index 915d2e21..2e515a10 100644 --- a/clapper_src/revealers.js +++ b/clapper_src/revealers.js @@ -229,3 +229,74 @@ class ClapperRevealerBottom extends CustomRevealer } } }); + +var ButtonsRevealer = GObject.registerClass( +class ClapperButtonsRevealer extends Gtk.Revealer +{ + _init(trType, toggleButton) + { + super._init({ + transition_duration: 500, + transition_type: Gtk.RevealerTransitionType[trType], + }); + + let revealerBox = new Gtk.Box({ + orientation: Gtk.Orientation.HORIZONTAL, + }); + this.set_child(revealerBox); + + if(toggleButton) { + toggleButton.connect('clicked', this._onToggleButtonClicked.bind(this)); + this.connect('notify::reveal-child', this._onRevealChild.bind(this, toggleButton)); + this.connect('notify::child-revealed', this._onChildRevealed.bind(this, toggleButton)); + } + } + + set_reveal_child(isReveal) + { + if(this.reveal_child === isReveal) + return; + + let grandson = this.child.get_first_child(); + if(grandson && grandson.isFloating && !grandson.isFullscreen) + return; + + super.set_reveal_child(isReveal); + } + + append(widget) + { + this.get_child().append(widget); + } + + _setRotateClass(button, isAdd) + { + const cssClass = 'buttonrotate'; + const hasClass = button.has_css_class(cssClass); + + if(!hasClass && isAdd) + button.add_css_class(cssClass); + else if(hasClass && !isAdd) + button.remove_css_class(cssClass); + } + + _onToggleButtonClicked(button) + { + this.set_reveal_child(!this.reveal_child); + } + + _onRevealChild(button) + { + this._setRotateClass(button, true); + } + + _onChildRevealed(button) + { + if(!this.child_revealed) + button.setPrimaryIcon(); + else + button.setSecondaryIcon(); + + this._setRotateClass(button, false); + } +}); diff --git a/css/styles.css b/css/styles.css index 4b5a47d7..81503647 100644 --- a/css/styles.css +++ b/css/styles.css @@ -124,6 +124,20 @@ scale marks { min-height: 12px; } +.narrowbutton { + min-width: 8px; +} +@keyframes halfrotate { + to { transform: rotate(0.5turn); } +} +.buttonrotate { + animation-name: halfrotate; + animation-duration: 200ms; + animation-delay: 302ms; + animation-timing-function: linear; + animation-iteration-count: 1; +} + /* Preferences */ .prefsnotebook grid { margin: 10px;