mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
390 lines
13 KiB
QML
390 lines
13 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.Widgets
|
|
|
|
DankPopout {
|
|
id: root
|
|
|
|
layerNamespace: "dms:dash"
|
|
|
|
property bool dashVisible: false
|
|
property var triggerScreen: null
|
|
property int currentTabIndex: 0
|
|
|
|
popupWidth: 700
|
|
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 500
|
|
triggerWidth: 80
|
|
screen: triggerScreen
|
|
shouldBeVisible: dashVisible
|
|
|
|
property bool __focusArmed: false
|
|
property bool __contentReady: false
|
|
|
|
property var __mediaTabRef: null
|
|
|
|
property int __dropdownType: 0
|
|
property point __dropdownAnchor: Qt.point(0, 0)
|
|
property bool __dropdownRightEdge: false
|
|
property var __dropdownPlayer: null
|
|
property var __dropdownPlayers: []
|
|
|
|
function __showVolumeDropdown(pos, rightEdge, player, players) {
|
|
__dropdownAnchor = pos;
|
|
__dropdownRightEdge = rightEdge;
|
|
__dropdownPlayer = player;
|
|
__dropdownPlayers = players;
|
|
__dropdownType = 1;
|
|
}
|
|
|
|
function __showAudioDevicesDropdown(pos, rightEdge) {
|
|
__dropdownAnchor = pos;
|
|
__dropdownRightEdge = rightEdge;
|
|
__dropdownType = 2;
|
|
}
|
|
|
|
function __showPlayersDropdown(pos, rightEdge, player, players) {
|
|
__dropdownAnchor = pos;
|
|
__dropdownRightEdge = rightEdge;
|
|
__dropdownPlayer = player;
|
|
__dropdownPlayers = players;
|
|
__dropdownType = 3;
|
|
}
|
|
|
|
function __hideDropdowns() {
|
|
__volumeCloseTimer.stop();
|
|
__dropdownType = 0;
|
|
__mediaTabRef?.resetDropdownStates();
|
|
}
|
|
|
|
function __startCloseTimer() {
|
|
__volumeCloseTimer.restart();
|
|
}
|
|
|
|
function __stopCloseTimer() {
|
|
__volumeCloseTimer.stop();
|
|
}
|
|
|
|
Timer {
|
|
id: __volumeCloseTimer
|
|
interval: 400
|
|
onTriggered: {
|
|
if (__dropdownType === 1) {
|
|
__hideDropdowns();
|
|
}
|
|
}
|
|
}
|
|
|
|
overlayContent: Component {
|
|
MediaDropdownOverlay {
|
|
dropdownType: root.__dropdownType
|
|
anchorPos: root.__dropdownAnchor
|
|
isRightEdge: root.__dropdownRightEdge
|
|
activePlayer: root.__dropdownPlayer
|
|
allPlayers: root.__dropdownPlayers
|
|
onCloseRequested: root.__hideDropdowns()
|
|
onPanelEntered: root.__stopCloseTimer()
|
|
onPanelExited: root.__startCloseTimer()
|
|
onVolumeChanged: volume => {
|
|
const player = root.__dropdownPlayer;
|
|
const isChrome = player?.identity?.toLowerCase().includes("chrome") || player?.identity?.toLowerCase().includes("chromium");
|
|
const usePlayerVolume = player && player.volumeSupported && !isChrome;
|
|
if (usePlayerVolume) {
|
|
player.volume = volume;
|
|
} else if (AudioService.sink?.audio) {
|
|
AudioService.sink.audio.volume = volume;
|
|
}
|
|
}
|
|
onPlayerSelected: player => {
|
|
const currentPlayer = MprisController.activePlayer;
|
|
if (currentPlayer && currentPlayer !== player && currentPlayer.canPause) {
|
|
currentPlayer.pause();
|
|
}
|
|
MprisController.activePlayer = player;
|
|
root.__hideDropdowns();
|
|
}
|
|
onDeviceSelected: device => {
|
|
root.__hideDropdowns();
|
|
}
|
|
}
|
|
}
|
|
|
|
function __tryFocusOnce() {
|
|
if (!__focusArmed)
|
|
return;
|
|
const win = root.window;
|
|
if (!win || !win.visible)
|
|
return;
|
|
if (!contentLoader.item)
|
|
return;
|
|
if (win.requestActivate)
|
|
win.requestActivate();
|
|
contentLoader.item.forceActiveFocus(Qt.TabFocusReason);
|
|
|
|
if (contentLoader.item.activeFocus)
|
|
__focusArmed = false;
|
|
}
|
|
|
|
onDashVisibleChanged: {
|
|
if (dashVisible) {
|
|
__focusArmed = true;
|
|
__contentReady = !!contentLoader.item;
|
|
open();
|
|
__tryFocusOnce();
|
|
} else {
|
|
__focusArmed = false;
|
|
__contentReady = false;
|
|
__hideDropdowns();
|
|
close();
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: contentLoader
|
|
function onLoaded() {
|
|
__contentReady = true;
|
|
if (__focusArmed)
|
|
__tryFocusOnce();
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root.window ? root.window : null
|
|
enabled: !!root.window
|
|
function onVisibleChanged() {
|
|
if (__focusArmed)
|
|
__tryFocusOnce();
|
|
}
|
|
}
|
|
|
|
onBackgroundClicked: {
|
|
dashVisible = false;
|
|
}
|
|
|
|
content: Component {
|
|
Rectangle {
|
|
id: mainContainer
|
|
|
|
implicitHeight: contentColumn.height + Theme.spacingM * 2
|
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
|
radius: Theme.cornerRadius
|
|
focus: true
|
|
|
|
Component.onCompleted: {
|
|
if (root.shouldBeVisible) {
|
|
mainContainer.forceActiveFocus();
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root
|
|
function onShouldBeVisibleChanged() {
|
|
if (root.shouldBeVisible) {
|
|
Qt.callLater(function () {
|
|
mainContainer.forceActiveFocus();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
Keys.onPressed: function (event) {
|
|
if (event.key === Qt.Key_Escape) {
|
|
root.dashVisible = false;
|
|
event.accepted = true;
|
|
return;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Tab && !(event.modifiers & Qt.ShiftModifier)) {
|
|
let nextIndex = root.currentTabIndex + 1;
|
|
while (nextIndex < tabBar.model.length && tabBar.model[nextIndex] && tabBar.model[nextIndex].isAction) {
|
|
nextIndex++;
|
|
}
|
|
if (nextIndex >= tabBar.model.length) {
|
|
nextIndex = 0;
|
|
}
|
|
root.currentTabIndex = nextIndex;
|
|
event.accepted = true;
|
|
return;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && (event.modifiers & Qt.ShiftModifier))) {
|
|
let prevIndex = root.currentTabIndex - 1;
|
|
while (prevIndex >= 0 && tabBar.model[prevIndex] && tabBar.model[prevIndex].isAction) {
|
|
prevIndex--;
|
|
}
|
|
if (prevIndex < 0) {
|
|
prevIndex = tabBar.model.length - 1;
|
|
while (prevIndex >= 0 && tabBar.model[prevIndex] && tabBar.model[prevIndex].isAction) {
|
|
prevIndex--;
|
|
}
|
|
}
|
|
if (prevIndex >= 0) {
|
|
root.currentTabIndex = prevIndex;
|
|
}
|
|
event.accepted = true;
|
|
return;
|
|
}
|
|
|
|
if (root.currentTabIndex === 2 && wallpaperTab.handleKeyEvent) {
|
|
if (wallpaperTab.handleKeyEvent(event)) {
|
|
event.accepted = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: contentColumn
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: Theme.spacingM
|
|
spacing: Theme.spacingS
|
|
|
|
DankTabBar {
|
|
id: tabBar
|
|
|
|
width: parent.width
|
|
height: 48
|
|
currentIndex: root.currentTabIndex
|
|
spacing: Theme.spacingS
|
|
equalWidthTabs: true
|
|
enableArrowNavigation: false
|
|
focus: false
|
|
activeFocusOnTab: false
|
|
nextFocusTarget: {
|
|
const item = pages.currentItem;
|
|
if (!item)
|
|
return null;
|
|
if (item.focusTarget)
|
|
return item.focusTarget;
|
|
return item;
|
|
}
|
|
|
|
model: {
|
|
let tabs = [
|
|
{
|
|
"icon": "dashboard",
|
|
"text": I18n.tr("Overview")
|
|
},
|
|
{
|
|
"icon": "music_note",
|
|
"text": I18n.tr("Media")
|
|
},
|
|
{
|
|
"icon": "wallpaper",
|
|
"text": I18n.tr("Wallpapers")
|
|
}
|
|
];
|
|
|
|
if (SettingsData.weatherEnabled) {
|
|
tabs.push({
|
|
"icon": "wb_sunny",
|
|
"text": I18n.tr("Weather")
|
|
});
|
|
}
|
|
|
|
tabs.push({
|
|
"icon": "settings",
|
|
"text": I18n.tr("Settings"),
|
|
"isAction": true
|
|
});
|
|
return tabs;
|
|
}
|
|
|
|
onTabClicked: function (index) {
|
|
root.currentTabIndex = index;
|
|
}
|
|
|
|
onActionTriggered: function (index) {
|
|
let settingsIndex = SettingsData.weatherEnabled ? 4 : 3;
|
|
if (index === settingsIndex) {
|
|
dashVisible = false;
|
|
settingsModal.show();
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: Theme.spacingXS
|
|
}
|
|
|
|
StackLayout {
|
|
id: pages
|
|
width: parent.width
|
|
implicitHeight: {
|
|
if (currentIndex === 0)
|
|
return overviewTab.implicitHeight;
|
|
if (currentIndex === 1)
|
|
return mediaTab.implicitHeight;
|
|
if (currentIndex === 2)
|
|
return wallpaperTab.implicitHeight;
|
|
if (SettingsData.weatherEnabled && currentIndex === 3)
|
|
return weatherTab.implicitHeight;
|
|
return overviewTab.implicitHeight;
|
|
}
|
|
currentIndex: root.currentTabIndex
|
|
|
|
OverviewTab {
|
|
id: overviewTab
|
|
|
|
onCloseDash: {
|
|
root.dashVisible = false;
|
|
}
|
|
|
|
onSwitchToWeatherTab: {
|
|
if (SettingsData.weatherEnabled) {
|
|
tabBar.currentIndex = 3;
|
|
tabBar.tabClicked(3);
|
|
}
|
|
}
|
|
|
|
onSwitchToMediaTab: {
|
|
tabBar.currentIndex = 1;
|
|
tabBar.tabClicked(1);
|
|
}
|
|
}
|
|
|
|
MediaPlayerTab {
|
|
id: mediaTab
|
|
targetScreen: root.screen
|
|
popoutX: root.alignedX
|
|
popoutY: root.alignedY
|
|
popoutWidth: root.alignedWidth
|
|
popoutHeight: root.alignedHeight
|
|
contentOffsetY: Theme.spacingM + 48 + Theme.spacingS + Theme.spacingXS
|
|
Component.onCompleted: root.__mediaTabRef = this
|
|
onShowVolumeDropdown: (pos, screen, rightEdge, player, players) => {
|
|
root.__showVolumeDropdown(pos, rightEdge, player, players);
|
|
}
|
|
onShowAudioDevicesDropdown: (pos, screen, rightEdge) => {
|
|
root.__showAudioDevicesDropdown(pos, rightEdge);
|
|
}
|
|
onShowPlayersDropdown: (pos, screen, rightEdge, player, players) => {
|
|
root.__showPlayersDropdown(pos, rightEdge, player, players);
|
|
}
|
|
onHideDropdowns: root.__hideDropdowns()
|
|
onVolumeButtonExited: root.__startCloseTimer()
|
|
}
|
|
|
|
WallpaperTab {
|
|
id: wallpaperTab
|
|
active: root.currentTabIndex === 2
|
|
tabBarItem: tabBar
|
|
keyForwardTarget: mainContainer
|
|
targetScreen: root.triggerScreen
|
|
parentPopout: root
|
|
}
|
|
|
|
WeatherTab {
|
|
id: weatherTab
|
|
visible: SettingsData.weatherEnabled && root.currentTabIndex === 3
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|