diff --git a/resources.qrc b/resources.qrc index 8771c776a08d7..18091d179e764 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,5 +1,8 @@ + src/gui/nmcgui/qmldir + src/gui/nmcgui/NMCHeaderButton.qml + src/gui/nmcgui/NMCMenuItem.qml src/gui/UserStatusMessageView.qml src/gui/UserStatusSelectorPage.qml src/gui/EmojiPicker.qml diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 54d32c3580e86..b97a015acce5a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -6,6 +6,9 @@ find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Widgets Svg Qml Quick Qui find_package(KF6Archive REQUIRED) find_package(KF6GuiAddons) +#NMC customization: needed to find the ui file in a different location than the header file +set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/src/gui") + if(CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DQT_QML_DEBUG) endif() @@ -23,6 +26,9 @@ endif() configure_file(${CMAKE_SOURCE_DIR}/theme.qrc.in ${CMAKE_SOURCE_DIR}/theme.qrc) set(theme_dir ${CMAKE_SOURCE_DIR}/theme) +#NMC customization: needed to find the ui file in a different location than the header file +set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/src/gui") + set(client_UI_SRCS accountsettings.ui conflictdialog.ui @@ -260,6 +266,10 @@ set(client_SRCS wizard/wizardproxysettingsdialog.cpp ) +file(GLOB NMC_FILES "nmcgui/*") +set(NMC_SRCS ${NMC_FILES}) +list(APPEND client_SRCS ${NMC_SRCS}) + if (NOT DISABLE_ACCOUNT_MIGRATION) list(APPEND client_SRCS legacyaccountselectiondialog.h diff --git a/src/gui/nmcgui/NMCHeaderButton.qml b/src/gui/nmcgui/NMCHeaderButton.qml new file mode 100644 index 0000000000000..560019eb014a2 --- /dev/null +++ b/src/gui/nmcgui/NMCHeaderButton.qml @@ -0,0 +1,65 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import Style +import com.nextcloud.desktopclient + +Item { + id: rec + + width: 92 + height: Style.nmcTrayWindowHeaderHeight + + signal clickedButton + + property string iconText: "" + property string iconSource: "" + property bool iconHovered: false + + ColumnLayout { + spacing: 0 + anchors.centerIn: parent + + Button { + id: button + flat: true + focusPolicy: Qt.NoFocus + Layout.alignment: Qt.AlignHCenter + + contentItem: Image { + source: rec.iconSource + width: Style.nmcTrayWindowIconWidth + height: Style.nmcTrayWindowIconWidth + fillMode: Image.PreserveAspectFit + anchors.centerIn: parent + } + + background: Rectangle { + color: rec.iconHovered || button.visualFocus ? "black" : "transparent" + opacity: 0.05 + radius: 4 + } + + MouseArea { + id: buttonArea + anchors.fill: parent + onClicked: rec.clickedButton() // Trigger the button click signal + } + + // Optional: Handle hover on icon to change its state + onClicked: rec.clickedButton() + } + + Text { + width: rec.width + text: rec.iconText + elide: Text.ElideRight + color: Style.nmcTrayWindowHeaderTextColor + font.pixelSize: Style.nmcFontSizeIconText + horizontalAlignment: Text.AlignHCenter + leftPadding: 8 + rightPadding: 8 + } + } +} diff --git a/src/gui/nmcgui/NMCMenuItem.qml b/src/gui/nmcgui/NMCMenuItem.qml new file mode 100644 index 0000000000000..76c18dbb53992 --- /dev/null +++ b/src/gui/nmcgui/NMCMenuItem.qml @@ -0,0 +1,37 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import Style + +MenuItem { + id: root + + contentItem: RowLayout { + spacing: 8 + anchors.fill: parent + anchors.leftMargin: 12 + + Image { + source: root.icon.source + visible: root.icon.source !== "" + width: Style.nmcTrayWindowIconWidth + height: Style.nmcTrayWindowIconWidth + fillMode: Image.PreserveAspectFit + } + + Text { + text: root.text + color: hovered ? Style.nmcTrayWindowHeaderTextColor : Style.nmcTrayWindowHeaderTextColor + font.pixelSize: Style.topLinePixelSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + elide: Text.ElideRight + Layout.fillWidth: true + } + } + + background: Rectangle { + color: root.hovered ? Style.nmcTrayWindowHeaderHighlightColor : "transparent" + } +} diff --git a/src/gui/nmcgui/qmldir b/src/gui/nmcgui/qmldir new file mode 100644 index 0000000000000..9bc50ef6383cc --- /dev/null +++ b/src/gui/nmcgui/qmldir @@ -0,0 +1,3 @@ +module NMCGui +NMCHeaderButton 1.0 NMCHeaderButton.qml +NMCMenuItem 1.0 NMCMenuItem.qml \ No newline at end of file diff --git a/src/gui/nmcgui/qmldir.txt b/src/gui/nmcgui/qmldir.txt new file mode 100644 index 0000000000000..9bc50ef6383cc --- /dev/null +++ b/src/gui/nmcgui/qmldir.txt @@ -0,0 +1,3 @@ +module NMCGui +NMCHeaderButton 1.0 NMCHeaderButton.qml +NMCMenuItem 1.0 NMCMenuItem.qml \ No newline at end of file diff --git a/src/gui/tray/ActivityItem.qml b/src/gui/tray/ActivityItem.qml index 6af9ec3c16522..94df9747b22e1 100644 --- a/src/gui/tray/ActivityItem.qml +++ b/src/gui/tray/ActivityItem.qml @@ -24,6 +24,11 @@ ItemDelegate { property bool isTalkReplyOptionVisible: model.messageSent !== "" padding: Style.standardSpacing + focusPolicy: Qt.NoFocus + background: Rectangle { + color: "transparent" + border.width: 0 + } Accessible.role: Accessible.ListItem Accessible.name: (model.path !== "" && model.displayPath !== "") ? qsTr("Open %1 locally").arg(model.displayPath) : model.message diff --git a/src/gui/tray/ActivityItemActions.qml b/src/gui/tray/ActivityItemActions.qml index 3997f9250f6e8..7ddaad27e2ee1 100644 --- a/src/gui/tray/ActivityItemActions.qml +++ b/src/gui/tray/ActivityItemActions.qml @@ -50,5 +50,25 @@ Repeater { onClicked: isTalkReplyButton ? root.showReplyField() : root.triggerAction(model.index) visible: verb !== "REPLY" || (verb === "REPLY" && root.talkReplyButtonVisible) + + HoverHandler { + id: mouse + acceptedDevices: PointerDevice.AllPointerTypes + } + + background: Rectangle { + color: mouse.hovered ? Style.nmcConflictHoverColor : Style.nmcConflictColor + radius: Style.nmcStandardRadius + height: Style.nmcTraySyncButtonHeight + } + + contentItem: Text { + text: activityActionButton.text + color: mouse.hovered ? Style.nmcTextInButtonColor : Style.nmcTextInButtonColor + font.pixelSize: Style.fontSizeSmall + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } } } diff --git a/src/gui/tray/ActivityItemContent.qml b/src/gui/tray/ActivityItemContent.qml index 2260ed8e6e296..b22f457684b50 100644 --- a/src/gui/tray/ActivityItemContent.qml +++ b/src/gui/tray/ActivityItemContent.qml @@ -33,8 +33,8 @@ RowLayout { Item { id: thumbnailItem - readonly property int imageWidth: width * (1 - Style.thumbnailImageSizeReduction) - readonly property int imageHeight: height * (1 - Style.thumbnailImageSizeReduction) + readonly property int imageWidth: width + readonly property int imageHeight: height readonly property int thumbnailRadius: model.thumbnail && model.thumbnail.isUserAvatar ? width / 2 : 3 implicitWidth: root.iconSize @@ -184,7 +184,7 @@ RowLayout { } display: Button.IconOnly - visible: model.showFileDetails + visible: false onClicked: Systray.presentShareViewInTray(model.openablePath) } diff --git a/src/gui/tray/ActivityList.qml b/src/gui/tray/ActivityList.qml index e2e43c3492707..5840ceb69f0f0 100644 --- a/src/gui/tray/ActivityList.qml +++ b/src/gui/tray/ActivityList.qml @@ -98,7 +98,8 @@ ScrollView { width: activityList.contentItem.width isFileActivityList: controlRoot.isFileActivityList - iconSize: controlRoot.iconSize + iconSize: Style.nmcListViewIconSize + leftPadding: Style.nmcListViewLeftPadding flickable: activityList onHoveredChanged: if (hovered) { // When we set the currentIndex the list view will scroll... @@ -150,7 +151,7 @@ ScrollView { Column { id: placeholderColumn - width: parent.width * 0.8 + width: parent.width * 0.75 anchors.centerIn: parent visible: activityList.count === 0 spacing: Style.standardSpacing diff --git a/src/gui/tray/CurrentAccountHeaderButton.qml b/src/gui/tray/CurrentAccountHeaderButton.qml index 322dbaf0d1c2f..8d3eff5eaf167 100644 --- a/src/gui/tray/CurrentAccountHeaderButton.qml +++ b/src/gui/tray/CurrentAccountHeaderButton.qml @@ -9,10 +9,10 @@ import QtQuick.Layouts import "../" import "../filedetails/" +import "qrc:/qml/NMCGui" import Style import com.nextcloud.desktopclient -import com.nextcloud.desktopclient as NC Button { id: root @@ -23,18 +23,20 @@ Button { display: AbstractButton.IconOnly flat: true + hoverEnabled: true + + background: Rectangle { + color: root.hovered ? Style.nmcTrayWindowHeaderHighlightColor : "transparent" + radius: 4 + } + + Layout.preferredWidth: Style.nmcCurrentAccountButtonWidth + Layout.preferredHeight: Style.nmcTrayWindowHeaderHeight Accessible.role: Accessible.ButtonMenu Accessible.name: qsTr("Current account") Accessible.onPressAction: root.clicked() - palette { - text: Style.currentUserHeaderTextColor - windowText: Style.currentUserHeaderTextColor - buttonText: Style.currentUserHeaderTextColor - button: Style.adjustedCurrentUserHeaderColor - } - // We call open() instead of popup() because we want to position it // exactly below the dropdown button, not the mouse onClicked: { @@ -51,17 +53,15 @@ Button { // x coordinate grows towards the right // y coordinate grows towards the bottom - x: (root.x + 2) - y: (root.y + Style.trayWindowHeaderHeight + 2) + x: (0 - Style.nmcTrayWindowLogoWidth) + y: (root.y + Style.nmcTrayWindowHeaderHeight - Style.nmcTrayWindowMenuOverlayMargin) - property real widestMenuItemWidth: 0 - property real maximumWidthAllowed: trayWindowHeader.width - (root.x + 4) - width: Math.min( widestMenuItemWidth + leftPadding + rightPadding, maximumWidthAllowed ) + width: (Style.nmcCurrentAccountButtonWidth + Style.nmcTrayWindowLogoWidth + 64) height: Math.min(implicitHeight, maxMenuHeight) closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape onClosed: { - // HACK: reload account Instantiator immediately by resetting it - could be done better I guess + // HACK: reload account Instantiator immediately by restting it - could be done better I guess // see also onVisibleChanged above userLineInstantiator.active = false; userLineInstantiator.active = true; @@ -74,41 +74,12 @@ Button { implicitHeight: instantiatedUserLine.height UserLine { id: instantiatedUserLine - width: Math.min(accountMenu.widestMenuItemWidth, accountMenu.maximumWidthAllowed) - - Component.onCompleted: { - instantiatedUserLine.updateMenuWidth() - } - - onImplicitWidthChanged: { - instantiatedUserLine.updateMenuWidth() - } - - Connections { - target: model - function onNameChanged() { - instantiatedUserLine.updateMenuWidth() - } - - function onStatusChanged() { - instantiatedUserLine.updateMenuWidth() - } - } - + width: parent.width onShowUserStatusSelector: { userStatusDrawer.openUserStatusDrawer(model.index); accountMenu.close(); } - onShowUserStatusMessageSelector: { - userStatusDrawer.openUserStatusMessageDrawer(model.index); - accountMenu.close(); - } onClicked: UserModel.currentUserId = model.index; - - function updateMenuWidth() - { - accountMenu.widestMenuItemWidth = Math.max( instantiatedUserLine.implicitWidth, accountMenu.widestMenuItemWidth ) - } } } onObjectAdded: function(index, object) { @@ -119,139 +90,104 @@ Button { } } - MenuItem { - id: addAccountButton - hoverEnabled: true - visible: Systray.enableAddAccount - implicitHeight: Style.trayWindowHeaderHeight - - readonly property real addAccountIconSize: Style.accountAvatarSize * Style.smallIconScaleFactor - readonly property real addAccountHorizontalOffset: ( (Style.accountAvatarSize - addAccountIconSize) / 2 ) + Style.accountIconsMenuMargin - property var iconColor: !addAccountButton.enabled - ? addAccountButton.palette.mid - : ((addAccountButton.highlighted || addAccountButton.down) && Qt.platform.os !== "windows" - ? addAccountButton.palette.highlightedText - : addAccountButton.palette.text) - - icon.source: "image://svgimage-custom-color/add.svg/" + iconColor - icon.width: addAccountIconSize - icon.height: addAccountIconSize - leftPadding: addAccountHorizontalOffset - spacing: Style.userLineSpacing - text: qsTr("Add account") - onClicked: UserModel.addAccount() - - Accessible.role: Accessible.MenuItem - Accessible.name: qsTr("Add new account") - Accessible.onPressAction: addAccountButton.clicked() + MenuSeparator { + padding: 0 + topPadding: 6 + bottomPadding: 6 + contentItem: Rectangle { + implicitHeight: 1 + color: Style.nmcTrayWindowHeaderSeparatorColor + } } - MenuSeparator {} - - MenuItem { + NMCMenuItem { id: syncPauseButton - height: Systray.anySyncFolders ? implicitHeight : 0 - font.pixelSize: Style.topLinePixelSize - hoverEnabled: true + + icon.source: Style.nmcPauseIcon + icon.height: Style.nmcTrayWindowIconWidth + icon.width: Style.nmcTrayWindowIconWidth + leftPadding: Style.nmcMenuSubItemLeftPadding + height: Style.nmcMenuSubItemHeight + enabled: Systray.anySyncFolders visible: Systray.anySyncFolders onClicked: Systray.syncIsPaused = !Systray.syncIsPaused Accessible.role: Accessible.MenuItem Accessible.name: Systray.syncIsPaused ? qsTr("Resume sync for all") : qsTr("Pause sync for all") Accessible.onPressAction: syncPauseButton.clicked() - - contentItem: Text { - text: parent.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - leftPadding: Style.userLineSpacing - elide: Text.ElideRight - color: !parent.enabled - ? parent.palette.mid - : ((parent.highlighted || parent.down) && Qt.platform.os !== "windows" - ? parent.palette.highlightedText - : parent.palette.text) - } } - MenuItem { + NMCMenuItem { id: settingsButton text: qsTr("Settings") - font.pixelSize: Style.topLinePixelSize - hoverEnabled: true + + icon.source: Style.nmcSettingsIcon + icon.height: Style.nmcTrayWindowIconWidth + icon.width: Style.nmcTrayWindowIconWidth + leftPadding: Style.nmcMenuSubItemLeftPadding + height: Style.nmcMenuSubItemHeight + onClicked: Systray.openSettings() Accessible.role: Accessible.MenuItem Accessible.name: text Accessible.onPressAction: settingsButton.clicked() - - contentItem: Text { - text: parent.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - leftPadding: Style.userLineSpacing - elide: Text.ElideRight - color: !parent.enabled - ? parent.palette.mid - : ((parent.highlighted || parent.down) && Qt.platform.os !== "windows" - ? parent.palette.highlightedText - : parent.palette.text) - } } - MenuItem { + NMCMenuItem { id: exitButton text: qsTr("Exit"); - font.pixelSize: Style.topLinePixelSize - hoverEnabled: true + + icon.source: Style.nmcCloseIcon + icon.height: Style.nmcTrayWindowIconWidth + icon.width: Style.nmcTrayWindowIconWidth + leftPadding: Style.nmcMenuSubItemLeftPadding + height: Style.nmcMenuSubItemHeight + onClicked: Systray.shutdown() Accessible.role: Accessible.MenuItem Accessible.name: text - Accessible.onPressAction: exitButton.clicked() - - contentItem: Text { - text: parent.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - leftPadding: Style.userLineSpacing - elide: Text.ElideRight - color: !parent.enabled - ? parent.palette.mid - : ((parent.highlighted || parent.down) && Qt.platform.os !== "windows" - ? parent.palette.highlightedText - : parent.palette.text) - } + Accessible.onPressAction: exitButton.clicked() + } + + // NMC customization: spacer at the bottom of the menu + Rectangle { + width: parent.width + height: 8 + color: "transparent" + anchors.horizontalCenter: parent.horizontalCenter } } - RowLayout { - id: accountControlRowLayout + Item { + anchors.fill: parent - height: Style.trayWindowHeaderHeight - width: Style.rootWidth - spacing: 0 + RowLayout { + id: accountControlRowLayout - Image { - id: currentAccountAvatar + anchors.verticalCenter: parent.verticalCenter + width: Style.nmcCurrentAccountButtonWidth + spacing: 0 - Layout.leftMargin: Style.trayHorizontalMargin - verticalAlignment: Qt.AlignCenter - cache: false - source: (UserModel.currentUser && UserModel.currentUser.avatar !== "") ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite" - Layout.preferredHeight: Style.accountAvatarSize - Layout.preferredWidth: Style.accountAvatarSize + Image { + id: currentAccountAvatar + + Layout.leftMargin: Style.trayHorizontalMargin + verticalAlignment: Qt.AlignCenter + cache: false + source: Style.nmcAccountAvatarIcon - Accessible.role: Accessible.Graphic - Accessible.name: qsTr("Current account avatar") + Accessible.role: Accessible.Graphic + Accessible.name: qsTr("Current account avatar") Rectangle { id: currentAccountStatusIndicatorBackground visible: UserModel.currentUser && UserModel.currentUser.isConnected && UserModel.currentUser.serverHasUserStatus - && UserModel.currentUser.status !== NC.userStatus.Invisible - && UserModel.currentUser.status !== NC.userStatus.Offline + && UserModel.currentUser.status !== UserStatus.Invisible + && UserModel.currentUser.status !== UserStatus.Offline width: Style.accountAvatarStateIndicatorSize + Style.trayFolderStatusIndicatorSizeOffset height: width - color: "white" + color: root.parentBackgroundColor anchors.bottom: currentAccountAvatar.bottom anchors.right: currentAccountAvatar.right radius: width * Style.trayFolderStatusIndicatorRadiusFactor @@ -261,8 +197,8 @@ Button { id: currentAccountStatusIndicator visible: UserModel.currentUser && UserModel.currentUser.isConnected && UserModel.currentUser.serverHasUserStatus - && UserModel.currentUser.status !== NC.userStatus.Invisible - && UserModel.currentUser.status !== NC.userStatus.Offline + && UserModel.currentUser.status !== UserStatus.Invisible + && UserModel.currentUser.status !== UserStatus.Offline source: UserModel.currentUser ? UserModel.currentUser.statusIcon : "" cache: false x: currentAccountStatusIndicatorBackground.x + Style.trayFolderStatusIndicatorSizeOffset / 2 @@ -270,84 +206,88 @@ Button { sourceSize.width: Style.accountAvatarStateIndicatorSize sourceSize.height: Style.accountAvatarStateIndicatorSize - Accessible.role: Accessible.Indicator - Accessible.name: UserModel.desktopNotificationsAllowed ? qsTr("Current account status is online") : qsTr("Current account status is do not disturb") - } - } - - Column { - id: accountLabels - spacing: Style.extraExtraSmallSpacing - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - Layout.leftMargin: Style.userStatusSpacing - Layout.fillWidth: true - Layout.maximumWidth: parent.width - - EnforcedPlainTextLabel { - id: currentAccountUser - Layout.alignment: Qt.AlignLeft | Qt.AlignBottom - width: Style.currentAccountLabelWidth - color: Style.currentUserHeaderTextColor - text: UserModel.currentUser ? UserModel.currentUser.name : "" - elide: Text.ElideRight - - font.pixelSize: Style.topLinePixelSize - font.bold: true - } - - EnforcedPlainTextLabel { - id: currentAccountServer - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - width: Style.currentAccountLabelWidth - color: Style.currentUserHeaderTextColor - text: UserModel.currentUser ? UserModel.currentUser.server : "" - font.pixelSize: Style.subLinePixelSize - elide: Text.ElideRight - visible: UserModel.numUsers() > 1 + Accessible.role: Accessible.Indicator + Accessible.name: UserModel.desktopNotificationsAllowed ? qsTr("Current account status is online") : qsTr("Current account status is do not disturb") + } } - RowLayout { - id: currentUserStatus - visible: UserModel.currentUser && UserModel.currentUser.isConnected && - UserModel.currentUser.serverHasUserStatus - width: parent.width + Column { + id: accountLabels + spacing: 0 + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.leftMargin: Style.userStatusSpacing + Layout.fillWidth: true EnforcedPlainTextLabel { - id: emoji - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - visible: UserModel.currentUser && UserModel.currentUser.statusEmoji !== "" - color: Style.currentUserHeaderTextColor - text: UserModel.currentUser ? UserModel.currentUser.statusEmoji : "" - font.pixelSize: Style.subLinePixelSize + id: currentAccountUser + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.fillWidth: true + width: Style.currentAccountLabelWidth + color: Style.nmcTrayWindowHeaderTextColor + text: UserModel.currentUser ? UserModel.currentUser.name : "" + elide: Text.ElideRight + + font.pixelSize: Style.topLinePixelSize + font.bold: false + palette.windowText: Style.nmcTrayWindowHeaderTextColor } + EnforcedPlainTextLabel { - id: message - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - Layout.fillWidth: true - visible: UserModel.currentUser && UserModel.currentUser.statusMessage !== "" + id: currentAccountServer + visible: false + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + width: Style.currentAccountLabelWidth color: Style.currentUserHeaderTextColor - text: UserModel.currentUser && UserModel.currentUser.statusMessage !== "" - ? UserModel.currentUser.statusMessage - : UserModel.currentUser ? UserModel.currentUser.server : "" - font.pixelSize: Style.subLinePixelSize + text: UserModel.currentUser ? UserModel.currentUser.server : "" elide: Text.ElideRight } - } - } - Loader { - active: root.indicator === null - sourceComponent: Image { - Layout.alignment: Qt.AlignRight - verticalAlignment: Qt.AlignCenter - horizontalAlignment: Qt.AlignRight - Layout.leftMargin: Style.accountDropDownCaretMargin - source: "image://svgimage-custom-color/caret-down.svg/" + palette.windowText - sourceSize.width: Style.accountDropDownCaretSize - sourceSize.height: Style.accountDropDownCaretSize - Accessible.role: Accessible.PopupMenu - Accessible.name: qsTr("Account switcher and settings menu") + RowLayout { + id: currentUserStatus + visible: UserModel.currentUser && UserModel.currentUser.isConnected && + UserModel.currentUser.serverHasUserStatus + spacing: Style.accountLabelsSpacing + width: parent.width + + EnforcedPlainTextLabel { + id: emoji + visible: UserModel.currentUser && UserModel.currentUser.statusEmoji !== "" + width: Style.userStatusEmojiSize + color: Style.currentUserHeaderTextColor + text: UserModel.currentUser ? UserModel.currentUser.statusEmoji : "" + } + EnforcedPlainTextLabel { + id: message + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.fillWidth: true + visible: UserModel.currentUser && UserModel.currentUser.statusMessage !== "" + width: Style.currentAccountLabelWidth + color: Style.currentUserHeaderTextColor + text: UserModel.currentUser && UserModel.currentUser.statusMessage !== "" + ? UserModel.currentUser.statusMessage + : UserModel.currentUser ? UserModel.currentUser.server : "" + elide: Text.ElideRight + font.pixelSize: Style.subLinePixelSize + } + } } } } -} + + Loader { + id: caretLoader + anchors.verticalCenter: parent.verticalCenter + anchors.right: root.right + anchors.rightMargin: 12 + active: root.indicator === null + + sourceComponent: Image { + source: "image://svgimage-custom-color/caret-down.svg/" + Style.nmcTrayWindowHeaderTextColor + sourceSize.width: Style.accountDropDownCaretSize + sourceSize.height: Style.accountDropDownCaretSize + + Accessible.role: Accessible.PopupMenu + Accessible.name: qsTr("Account switcher and settings menu") + } + } +} \ No newline at end of file diff --git a/src/gui/tray/MainWindow.qml b/src/gui/tray/MainWindow.qml index c70bdf34ac5bf..9848caa3e2225 100644 --- a/src/gui/tray/MainWindow.qml +++ b/src/gui/tray/MainWindow.qml @@ -13,6 +13,7 @@ import Qt.labs.platform as NativeDialogs import "../" import "../filedetails/" +import "qrc:/qml/NMCGui" // Custom qml modules are in /theme (and included by resources.qrc) import Style @@ -27,12 +28,12 @@ ApplicationWindow { title: Systray.windowTitle // If the main dialog is displayed as a regular window we want it to be quadratic - width: Systray.useNormalWindow ? Style.trayWindowHeight : Style.trayWindowWidth - height: Style.trayWindowHeight + width: Systray.useNormalWindow ? Style.nmcTrayWindowHeight : Style.nmcTrayWindowWidth + height: Style.nmcTrayWindowHeight flags: Systray.useNormalWindow ? Qt.Window : Qt.Dialog | Qt.FramelessWindowHint color: "transparent" - readonly property int maxMenuHeight: Style.trayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth + readonly property int maxMenuHeight: Style.nmcTrayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth Component.onCompleted: Systray.forceWindowInit(trayWindow) @@ -121,50 +122,50 @@ ApplicationWindow { } } - Drawer { - id: userStatusDrawer - width: parent.width - height: parent.height - Style.trayDrawerMargin - padding: 0 + Drawer { + id: userStatusDrawer + width: parent.width + height: parent.height - Style.trayDrawerMargin + padding: 0 edge: Qt.BottomEdge modal: true visible: false - - background: Rectangle { - radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius - border.width: Style.trayWindowBorderWidth - border.color: palette.dark - color: Style.colorWithoutTransparency(palette.base) - } - - property int userIndex: 0 - property string modeSetStatus: "setStatus" - property string modeStatusMessage: "statusMessage" - property string initialMode: modeSetStatus - - function openUserStatusDrawer(index, mode) { - console.log(`About to show dialog for user with index ${index}`); - userIndex = index; - initialMode = mode ? mode : modeSetStatus; - open(); - } - - function openUserStatusMessageDrawer(index) { - openUserStatusDrawer(index, modeStatusMessage); - } - - Loader { - id: userStatusContents - anchors.fill: parent - active: userStatusDrawer.visible - sourceComponent: UserStatusSelectorPage { - anchors.fill: parent - userIndex: userStatusDrawer.userIndex - mode: userStatusDrawer.initialMode - onFinished: userStatusDrawer.close() - } - } - } + + background: Rectangle { + radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius + border.width: Style.trayWindowBorderWidth + border.color: palette.dark + color: Style.colorWithoutTransparency(palette.base) + } + + property int userIndex: 0 + property string modeSetStatus: "setStatus" + property string modeStatusMessage: "statusMessage" + property string initialMode: modeSetStatus + + function openUserStatusDrawer(index, mode) { + console.log(`About to show dialog for user with index ${index}`); + userIndex = index; + initialMode = mode ? mode : modeSetStatus; + open(); + } + + function openUserStatusMessageDrawer(index) { + openUserStatusDrawer(index, modeStatusMessage); + } + + Loader { + id: userStatusContents + anchors.fill: parent + active: userStatusDrawer.visible + sourceComponent: UserStatusSelectorPage { + anchors.fill: parent + userIndex: userStatusDrawer.userIndex + mode: userStatusDrawer.initialMode + onFinished: userStatusDrawer.close() + } + } + } Drawer { id: fileDetailsDrawer @@ -251,16 +252,31 @@ ApplicationWindow { TrayWindowHeader { id: trayWindowHeader + height: Style.nmcTrayWindowHeaderHeight - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - height: Style.trayWindowHeaderHeight + anchors { + top: parent.top + left: parent.left + right: parent.right + } + } + + Rectangle { + id: separator + height: 1 + color: Style.nmcTrayWindowHeaderSeparatorColor + + anchors { + top: trayWindowHeader.bottom + left: trayWindowMainItem.left + right: trayWindowMainItem.right + } } UnifiedSearchInputContainer { id: trayWindowUnifiedSearchInputContainer + visible: false property bool activateSearchFocus: activeFocus anchors.top: trayWindowHeader.bottom @@ -282,7 +298,7 @@ ApplicationWindow { Rectangle { id: bottomUnifiedSearchInputSeparator - anchors.top: trayWindowUnifiedSearchInputContainer.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? trayWindowUnifiedSearchInputContainer.bottom : separator.bottom anchors.left: parent.left anchors.right: parent.right anchors.topMargin: Style.trayHorizontalMargin @@ -296,7 +312,7 @@ ApplicationWindow { id: unifiedSearchResultsErrorLabel visible: UserModel.currentUser.unifiedSearchResultsListModel.errorString && !unifiedSearchResultsListView.visible && ! UserModel.currentUser.unifiedSearchResultsListModel.isSearchInProgress && ! UserModel.currentUser.unifiedSearchResultsListModel.currentFetchMoreInProgressProviderId text: UserModel.currentUser.unifiedSearchResultsListModel.errorString - anchors.top: bottomUnifiedSearchInputSeparator.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? bottomUnifiedSearchInputSeparator.bottom : separator.bottom anchors.left: trayWindowMainItem.left anchors.right: trayWindowMainItem.right anchors.margins: Style.trayHorizontalMargin @@ -305,7 +321,7 @@ ApplicationWindow { UnifiedSearchPlaceholderView { id: unifiedSearchPlaceholderView - anchors.top: bottomUnifiedSearchInputSeparator.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? bottomUnifiedSearchInputSeparator.bottom : separator.bottom anchors.left: trayWindowMainItem.left anchors.right: trayWindowMainItem.right anchors.bottom: trayWindowMainItem.bottom @@ -317,7 +333,7 @@ ApplicationWindow { UnifiedSearchResultNothingFound { id: unifiedSearchResultNothingFound - anchors.top: bottomUnifiedSearchInputSeparator.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? bottomUnifiedSearchInputSeparator.bottom : separator.bottom anchors.left: trayWindowMainItem.left anchors.right: trayWindowMainItem.right anchors.topMargin: Style.trayHorizontalMargin @@ -335,7 +351,7 @@ ApplicationWindow { Loader { id: unifiedSearchResultsListViewSkeletonLoader - anchors.top: bottomUnifiedSearchInputSeparator.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? bottomUnifiedSearchInputSeparator.bottom : separator.bottom anchors.left: trayWindowMainItem.left anchors.right: trayWindowMainItem.right anchors.bottom: trayWindowMainItem.bottom @@ -364,7 +380,7 @@ ApplicationWindow { } visible: unifiedSearchResultsListView.count > 0 - anchors.top: bottomUnifiedSearchInputSeparator.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? bottomUnifiedSearchInputSeparator.bottom : separator.bottom anchors.left: trayWindowMainItem.left anchors.right: trayWindowMainItem.right anchors.bottom: trayWindowMainItem.bottom @@ -407,7 +423,7 @@ ApplicationWindow { accentColor: Style.accentColor visible: !trayWindowMainItem.isUnifiedSearchActive - anchors.top: trayWindowUnifiedSearchInputContainer.bottom + anchors.top: trayWindowUnifiedSearchInputContainer.visible ? trayWindowUnifiedSearchInputContainer.bottom : separator.bottom anchors.left: trayWindowMainItem.left anchors.right: trayWindowMainItem.right } @@ -483,6 +499,8 @@ ApplicationWindow { anchors.right: trayWindowMainItem.right anchors.bottom: trayWindowMainItem.bottom + ScrollBar.vertical.visible: contentHeight > activityList.height + activeFocusOnTab: true model: activityModel onOpenFile: Qt.openUrlExternally(filePath); diff --git a/src/gui/tray/NCProgressBar.qml b/src/gui/tray/NCProgressBar.qml index 839073da4b084..21cd9a7dffdc6 100644 --- a/src/gui/tray/NCProgressBar.qml +++ b/src/gui/tray/NCProgressBar.qml @@ -16,10 +16,10 @@ BasicControls.ProgressBar { background: Rectangle { implicitWidth: Style.progressBarWidth implicitHeight: Style.progressBarBackgroundHeight - radius: Style.progressBarRadius - color: palette.base + radius: Style.nmcStandardRadius + color: Style.nmcTrayWindowHeaderHighlightColor border.color: palette.dark - border.width: Style.progressBarBackgroundBorderWidth + border.width: 0 } contentItem: Item { @@ -30,9 +30,9 @@ BasicControls.ProgressBar { width: control.visualPosition * parent.width height: parent.height radius: Style.progressBarRadius - color: control.fillColor + color: Style.nmcTelekomMagentaColor border.color: palette.dark - border.width: Style.progressBarContentBorderWidth + border.width: 0 } } } diff --git a/src/gui/tray/SyncStatus.qml b/src/gui/tray/SyncStatus.qml index dacd84f1f4381..39ff88a8edaf2 100644 --- a/src/gui/tray/SyncStatus.qml +++ b/src/gui/tray/SyncStatus.qml @@ -18,6 +18,8 @@ RowLayout { property color accentColor: Style.ncBlue spacing: Style.trayHorizontalMargin + Layout.alignment: Qt.AlignVCenter + Layout.preferredHeight: Style.nmcTraySyncButtonHeight + 8 NC.SyncStatusSummary { id: syncStatus @@ -31,11 +33,11 @@ RowLayout { Layout.preferredWidth: size Layout.preferredHeight: size - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter Layout.topMargin: Style.trayHorizontalMargin Layout.rightMargin: whiteSpace * (0.5 + Style.thumbnailImageSizeReduction) Layout.bottomMargin: Style.trayHorizontalMargin - Layout.leftMargin: Style.trayHorizontalMargin + (whiteSpace * (0.5 - Style.thumbnailImageSizeReduction)) + Layout.leftMargin: Style.nmcListViewLeftPadding padding: 0 @@ -50,6 +52,7 @@ RowLayout { Layout.topMargin: 8 Layout.rightMargin: Style.trayHorizontalMargin Layout.bottomMargin: 8 + Layout.leftMargin: Style.nmcProgressFieldTextOffset Layout.fillWidth: true Layout.fillHeight: true @@ -60,7 +63,7 @@ RowLayout { text: syncStatus.syncStatusString verticalAlignment: Text.AlignVCenter - font.pixelSize: Style.topLinePixelSize + font.pixelSize: Style.nmcFontSizeSyncText font.bold: true wrapMode: Text.Wrap } @@ -85,7 +88,7 @@ RowLayout { Layout.fillWidth: true text: syncStatus.syncStatusDetailString - visible: syncStatus.syncStatusDetailString !== "" + visible: false font.pixelSize: Style.subLinePixelSize wrapMode: Text.Wrap } @@ -94,6 +97,7 @@ RowLayout { Button { id: syncNowButton + Layout.alignment: Qt.AlignVCenter Layout.rightMargin: Style.trayHorizontalMargin text: qsTr("Sync now") @@ -105,6 +109,27 @@ RowLayout { NC.UserModel.currentUser.hasLocalFolder && NC.UserModel.currentUser.isConnected enabled: visible + + HoverHandler { + id: mouseSync + acceptedDevices: PointerDevice.AllPointerTypes + } + + background: Rectangle { + color: mouseSync.hovered ? Style.nmcSyncHoverColor : Style.nmcTelekomMagentaColor + radius: Style.nmcStandardRadius + height: Style.nmcTraySyncButtonHeight + } + + contentItem: Text { + text: syncNowButton.text + color: "white" + font.pixelSize: Style.nmcFontSizeAccountName + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + onClicked: { if(!syncStatus.syncing) { NC.UserModel.currentUser.forceSyncNow(); @@ -113,8 +138,11 @@ RowLayout { } Button { + Layout.alignment: Qt.AlignVCenter Layout.rightMargin: Style.trayHorizontalMargin + padding: Style.smallSpacing + text: qsTr("Resolve conflicts") visible: activityModel.hasSyncConflicts && @@ -122,10 +150,34 @@ RowLayout { NC.UserModel.currentUser.hasLocalFolder && NC.UserModel.currentUser.isConnected enabled: visible + + HoverHandler { + id: mouseConflict + acceptedDevices: PointerDevice.Mouse + } + + contentItem: Text { + text: parent.text + color: Style.nmcTextInButtonColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + } + + background: Rectangle { + color: mouseConflict.hovered + ? Style.nmcConflictHoverColor + : Style.nmcConflictColor + radius: Style.nmcStandardRadius + height: Style.nmcTraySyncButtonHeight + width: parent.width + } + onClicked: NC.Systray.createResolveConflictsDialog(activityModel.allConflicts); } Button { + Layout.alignment: Qt.AlignVCenter Layout.rightMargin: Style.trayHorizontalMargin text: qsTr("Open browser") diff --git a/src/gui/tray/TrayWindowHeader.qml b/src/gui/tray/TrayWindowHeader.qml index bcc1260f648de..7c04c8036ff6d 100644 --- a/src/gui/tray/TrayWindowHeader.qml +++ b/src/gui/tray/TrayWindowHeader.qml @@ -9,6 +9,7 @@ import QtQuick.Layouts import "../" import "../filedetails/" +import "qrc:/qml/NMCGui" import Style import com.nextcloud.desktopclient @@ -17,10 +18,9 @@ Rectangle { id: root readonly property alias currentAccountHeaderButton: currentAccountHeaderButton - readonly property alias openLocalFolderButton: openLocalFolderButton - readonly property alias appsMenu: appsMenu - color: Style.currentUserHeaderColor + color: Style.nmcTrayWindowHeaderBackgroundColor + height: Style.nmcTrayWindowHeaderHeight palette { text: Style.currentUserHeaderTextColor @@ -29,11 +29,54 @@ Rectangle { button: Style.adjustedCurrentUserHeaderColor } + Rectangle { + id: whiteMargin + width: 10 + height: Style.nmcTrayWindowHeaderHeight + color: Style.nmcTrayWindowHeaderBackgroundColor + + anchors { + top: parent.top + left: parent.left + } + } + + Rectangle { + id: tLogo + width: Style.nmcTrayWindowLogoWidth + height: Style.nmcTrayWindowHeaderHeight + + anchors { + top: parent.top + left: whiteMargin.right + } + + Image { + anchors.fill: parent + source: Style.nmcTLogoPath + fillMode: Image.Stretch + cache: true + } + } + RowLayout { id: trayWindowHeaderLayout spacing: 0 - anchors.fill: parent + height: Style.nmcTrayWindowHeaderHeight + + anchors { + top: parent.top + left: tLogo.right + right: parent.right + } + + Rectangle { + id: whiteMarginLeft1 + Layout.preferredWidth: 10 + Layout.fillHeight: true + color: Style.nmcTrayWindowHeaderBackgroundColor + } CurrentAccountHeaderButton { id: currentAccountHeaderButton @@ -47,85 +90,69 @@ Rectangle { Layout.fillWidth: true } - TrayFoldersMenuButton { - id: openLocalFolderButton - - Layout.alignment: Qt.AlignRight - Layout.preferredWidth: Style.trayWindowHeaderHeight + Rectangle { + id: trayWindowWebsiteButtonContainer + Layout.preferredWidth: 92 Layout.fillHeight: true + color: websiteHover.hovered ? Style.nmcTrayWindowHeaderHighlightColor : "transparent" + + NMCHeaderButton { + id: trayWindowWebsiteButton + iconSource: Style.darkMode + ? "qrc:///client/theme/NMCIcons/website-white.svg" + : "qrc:///client/theme/NMCIcons/website.svg" + iconText: qsTranslate("", "OPEN_WEBSITE") + + MouseArea { + anchors.fill: parent + onClicked: UserModel.openCurrentAccountServer() + } + } - visible: currentUser.hasLocalFolder - currentUser: UserModel.currentUser - parentBackgroundColor: root.color - - onClicked: openLocalFolderButton.userHasGroupFolders ? openLocalFolderButton.toggleMenuOpen() : UserModel.openCurrentAccountLocalFolder() - - onFolderEntryTriggered: isGroupFolder ? UserModel.openCurrentAccountFolderFromTrayInfo(fullFolderPath) : UserModel.openCurrentAccountLocalFolder() - - Accessible.role: Accessible.Graphic - Accessible.name: qsTr("Open local or group folders") - Accessible.onPressAction: openLocalFolderButton.userHasGroupFolders ? openLocalFolderButton.toggleMenuOpen() : UserModel.openCurrentAccountLocalFolder() + HoverHandler { + id: websiteHover + acceptedDevices: PointerDevice.Mouse + } } - HeaderButton { - id: trayWindowFeaturedAppButton - - Layout.alignment: Qt.AlignRight - Layout.preferredWidth: Style.trayWindowHeaderHeight + Rectangle { + id: whiteMarginRight1 + Layout.preferredWidth: 10 Layout.fillHeight: true - visible: UserModel.currentUser.isFeaturedAppEnabled - icon.source: UserModel.currentUser.featuredAppIcon + "/" + palette.windowText - onClicked: UserModel.openCurrentAccountFeaturedApp() - - Accessible.role: Accessible.Button - Accessible.name: UserModel.currentUser.featuredAppAccessibleName - Accessible.onPressAction: trayWindowFeaturedAppButton.clicked() + color: Style.nmcTrayWindowHeaderBackgroundColor } - HeaderButton { - id: trayWindowAppsButton - icon.source: "image://svgimage-custom-color/more-apps.svg/" + palette.windowText - - onClicked: { - if(appsMenu.count <= 0) { - UserModel.openCurrentAccountServer() - } else if (appsMenu.visible) { - appsMenu.close() - } else { - appsMenu.open() + Rectangle { + id: trayWindowLocalButtonContainer + Layout.preferredWidth: 92 + Layout.fillHeight: true + color: localHover.hovered ? Style.nmcTrayWindowHeaderHighlightColor : "transparent" + + NMCHeaderButton { + id: trayWindowLocalButton + iconSource: Style.darkMode + ? "qrc:///client/theme/white/folder.svg" + : "qrc:///client/theme/black/folder.svg" + iconText: qsTranslate("", "LOCAL_FOLDER") + + MouseArea { + anchors.fill: parent + onClicked: UserModel.openCurrentAccountLocalFolder() } } - Accessible.role: Accessible.ButtonMenu - Accessible.name: qsTr("More apps") - Accessible.onPressAction: trayWindowAppsButton.clicked() - - Menu { - id: appsMenu - x: Style.trayWindowMenuOffsetX - y: (trayWindowAppsButton.y + trayWindowAppsButton.height + Style.trayWindowMenuOffsetY) - width: Style.trayWindowWidth * Style.trayWindowMenuWidthFactor - height: implicitHeight + y > Style.trayWindowHeight ? Style.trayWindowHeight - y : implicitHeight - closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape - - Repeater { - model: UserAppsModel - delegate: MenuItem { - id: appEntry - // HACK: Without creating our own component (and killing native styling) - // HACK: we do not have a way to adjust the text and icon spacing. - text: " " + model.appName - font.pixelSize: Style.topLinePixelSize - icon.source: model.appIconUrl - icon.color: palette.windowText - onTriggered: UserAppsModel.openAppUrl(appUrl) - Accessible.role: Accessible.MenuItem - Accessible.name: qsTr("Open %1 in browser").arg(model.appName) - Accessible.onPressAction: appEntry.triggered() - } - } + HoverHandler { + id: localHover + acceptedDevices: PointerDevice.Mouse } } + + Rectangle { + id: whiteMarginRight2 + Layout.preferredWidth: 10 + Layout.fillHeight: true + color: Style.nmcTrayWindowHeaderBackgroundColor + } } } diff --git a/src/gui/tray/UnifiedSearchInputContainer.qml b/src/gui/tray/UnifiedSearchInputContainer.qml index 4fd6ac4f1d927..535026ca9daeb 100644 --- a/src/gui/tray/UnifiedSearchInputContainer.qml +++ b/src/gui/tray/UnifiedSearchInputContainer.qml @@ -28,7 +28,7 @@ TextField { topPadding: topInset bottomPadding: bottomInset leftPadding: iconInset + leadingControlWidth + Style.smallSpacing - rightPadding: iconInset + trailingControlWidth + Style.smallSpacing + rightPadding: clearTextButton.width + iconInset + Style.smallSpacing verticalAlignment: Qt.AlignVCenter placeholderText: qsTr("Search files, messages, events …") diff --git a/src/gui/tray/UserLine.qml b/src/gui/tray/UserLine.qml index 43ab7480c7d31..51871205d542c 100644 --- a/src/gui/tray/UserLine.qml +++ b/src/gui/tray/UserLine.qml @@ -7,6 +7,7 @@ import QtQuick import QtQuick.Window import QtQuick.Controls import QtQuick.Layouts +import "qrc:/qml/NMCGui" // Custom qml modules are in /theme (and included by resources.qrc) import Style @@ -22,14 +23,15 @@ AbstractButton { Accessible.role: Accessible.MenuItem Accessible.name: qsTr("Switch to account") + " " + model.name - height: Style.trayWindowHeaderHeight + height: Style.nmcMenuSubItemHeight contentItem: RowLayout { id: userLineLayout - spacing: Style.userLineSpacing + spacing: 8 Image { id: accountAvatar + visible: false Layout.leftMargin: Style.accountIconsMenuMargin verticalAlignment: Qt.AlignCenter cache: false @@ -63,21 +65,34 @@ AbstractButton { } } - ColumnLayout { + RowLayout { id: accountLabels Layout.fillWidth: true Layout.fillHeight: true - spacing: Style.extraExtraSmallSpacing + Layout.alignment: Qt.AlignVCenter + spacing: 8 + + Item { width: Style.nmcMenuSubItemLeftPadding } + + Image { + id: accountIcon + source: Style.nmcAccountAvatarIcon + visible: true + width: Style.nmcTrayWindowIconWidth + height: Style.nmcTrayWindowIconWidth + fillMode: Image.PreserveAspectFit + Layout.alignment: Qt.AlignVCenter + } EnforcedPlainTextLabel { id: accountUser Layout.fillWidth: true - Layout.alignment: Qt.AlignLeft | Qt.AlignBottom - verticalAlignment: Text.AlignBottom + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter text: name elide: Text.ElideRight font.pixelSize: Style.topLinePixelSize - font.bold: true + font.bold: false color: !userLine.parent.enabled ? userLine.parent.palette.mid @@ -89,7 +104,7 @@ AbstractButton { RowLayout { id: statusLayout Layout.fillWidth: true - height: visible ? implicitHeight : 0 + Layout.preferredHeight: visible ? implicitHeight : 0 visible: model.isConnected && model.serverHasUserStatus && (model.statusEmoji !== "" || model.statusMessage !== "") @@ -124,6 +139,7 @@ AbstractButton { EnforcedPlainTextLabel { id: accountServer + visible: false Layout.fillWidth: true Layout.alignment: Qt.AlignLeft | Qt.AlignTop verticalAlignment: Text.AlignTop @@ -145,9 +161,12 @@ AbstractButton { Button { id: userMoreButton - Layout.preferredWidth: Style.headerButtonIconSize + Layout.preferredWidth: Style.iconButtonWidth Layout.fillHeight: true + Layout.rightMargin: Style.accountIconsMenuMargin flat: true + visible: true + opacity: 1 Accessible.role: Accessible.ButtonMenu Accessible.name: qsTr("Account actions") @@ -155,12 +174,9 @@ AbstractButton { onClicked: userMoreButtonMenu.visible ? userMoreButtonMenu.close() : userMoreButtonMenu.popup() - property var iconColor: !userLine.parent.enabled - ? userLine.parent.palette.mid - : (!hovered && ((userLine.parent.highlighted || userLine.parent.down) && Qt.platform.os !== "windows") - ? userLine.parent.palette.highlightedText - : userLine.parent.palette.text) - icon.source: "image://svgimage-custom-color/more.svg/" + iconColor + icon.source: Style.darkMode + ? "qrc:///client/theme/more-white.svg" + : "qrc:///client/theme/more.svg" AutoSizingMenu { id: userMoreButtonMenu @@ -169,10 +185,12 @@ AbstractButton { MenuItem { id: setStatusButton + visible: false enabled: model.isConnected && model.serverHasUserStatus text: qsTr("Set status") font.pixelSize: Style.topLinePixelSize hoverEnabled: true + height: visible ? implicitHeight : 0 onClicked: showUserStatusSelector(index) @@ -183,10 +201,12 @@ AbstractButton { MenuItem { id: statusMessageButton + visible: false enabled: model.isConnected && model.serverHasUserStatus text: qsTr("Status message") font.pixelSize: Style.topLinePixelSize hoverEnabled: true + height: visible ? implicitHeight : 0 onClicked: showUserStatusMessageSelector(index) @@ -195,13 +215,15 @@ AbstractButton { Accessible.onPressAction: statusMessageButton.clicked() } - MenuItem { + NMCMenuItem { id: logInOutButton enabled: model.canLogout text: model.isConnected ? qsTr("Log out") : qsTr("Log in") - width: parent.width - font.pixelSize: Style.topLinePixelSize - hoverEnabled: true + height: Style.nmcMenuSubItemHeight + icon.source: Style.nmcLogOutIcon + icon.height: Style.nmcTrayWindowIconWidth + icon.width: Style.nmcTrayWindowIconWidth + leftPadding: Style.nmcMenuSubItemLeftPadding onClicked: { if (model.isConnected) { @@ -214,14 +236,18 @@ AbstractButton { Accessible.role: Accessible.Button Accessible.name: text - Accessible.onPressAction: logInOutButton.clicked() + Accessible.onPressAction: clicked() } - MenuItem { + NMCMenuItem { id: removeAccountButton text: model.removeAccountText - font.pixelSize: Style.topLinePixelSize - hoverEnabled: true + height: Style.nmcMenuSubItemHeight + icon.source: Style.nmcRemoveIcon + icon.height: Style.nmcTrayWindowIconWidth + icon.width: Style.nmcTrayWindowIconWidth + leftPadding: Style.nmcMenuSubItemLeftPadding + onClicked: { UserModel.removeAccount(index) accountMenu.close() @@ -229,7 +255,7 @@ AbstractButton { Accessible.role: Accessible.Button Accessible.name: text - Accessible.onPressAction: removeAccountButton.clicked() + Accessible.onPressAction: clicked() } } } diff --git a/theme/NMCIcons/accountAvatarIcon-white.svg b/theme/NMCIcons/accountAvatarIcon-white.svg new file mode 100644 index 0000000000000..1071c83ea6ef8 --- /dev/null +++ b/theme/NMCIcons/accountAvatarIcon-white.svg @@ -0,0 +1,7 @@ + + + icon/user_file/user/default@svg + + + + \ No newline at end of file diff --git a/theme/NMCIcons/logout-white.svg b/theme/NMCIcons/logout-white.svg new file mode 100644 index 0000000000000..f449764e1a279 --- /dev/null +++ b/theme/NMCIcons/logout-white.svg @@ -0,0 +1,7 @@ + + + /svg/icon/action/logout/default + + + + \ No newline at end of file diff --git a/theme/NMCIcons/pause-white.svg b/theme/NMCIcons/pause-white.svg new file mode 100644 index 0000000000000..41fd92da98393 --- /dev/null +++ b/theme/NMCIcons/pause-white.svg @@ -0,0 +1,7 @@ + + + icon/action/pause/default@svg + + + + \ No newline at end of file diff --git a/theme/NMCIcons/remove-white.svg b/theme/NMCIcons/remove-white.svg new file mode 100644 index 0000000000000..9a71790bcff30 --- /dev/null +++ b/theme/NMCIcons/remove-white.svg @@ -0,0 +1,7 @@ + + + /svg/icon/action/remove/default + + + + \ No newline at end of file diff --git a/theme/NMCIcons/website-white.svg b/theme/NMCIcons/website-white.svg new file mode 100644 index 0000000000000..4db891a1afe17 --- /dev/null +++ b/theme/NMCIcons/website-white.svg @@ -0,0 +1,7 @@ + + + icon/content/news/default@svg + + + + \ No newline at end of file diff --git a/theme/Style/Style.qml b/theme/Style/Style.qml index 98856f8c8e126..ace1fa5c387d1 100644 --- a/theme/Style/Style.qml +++ b/theme/Style/Style.qml @@ -7,6 +7,52 @@ import QtQuick import com.nextcloud.desktopclient QtObject { + // NMC customization + readonly property int nmcFontSizeAccountName: 13 + readonly property int nmcFontSizeIconText: 10 + readonly property int nmcFontSizeSyncText: 15 + + // NMC icons + readonly property url nmcTLogoPath: "qrc:///client/theme/NMCIcons/tlogocarrier.svg" + readonly property url nmcAccountAvatarIcon: Theme.darkMode ? "qrc:///client/theme/NMCIcons/accountAvatarIcon-white.svg" : "qrc:///client/theme/NMCIcons/accountAvatarIcon.svg" + readonly property url nmcSettingsIcon: Theme.darkMode ? "qrc:///client/theme/settings-white.svg" : "qrc:///client/theme/settings.svg" + readonly property url nmcCloseIcon: Theme.darkMode ? "qrc:///client/theme/close-white.svg" : "qrc:///client/theme/close.svg" + readonly property url nmcPauseIcon: Theme.darkMode ? "qrc:///client/theme/NMCIcons/pause-white.svg" : "qrc:///client/theme/NMCIcons/pause.svg" + readonly property url nmcLogOutIcon: Theme.darkMode ? "qrc:///client/theme/NMCIcons/logout-white.svg" : "qrc:///client/theme/NMCIcons/logout.svg" + readonly property url nmcRemoveIcon: Theme.darkMode ? "qrc:///client/theme/NMCIcons/remove-white.svg" : "qrc:///client/theme/NMCIcons/remove.svg" + + // NMC colors + readonly property color nmcTelekomMagentaColor: "#E20074" + readonly property color nmcConflictColor: Theme.darkMode ? "#FFA14A" : "#F97012" + readonly property color nmcConflictHoverColor: Theme.darkMode ? "#f0802e" : "#de6310" + readonly property color nmcSyncHoverColor: Theme.darkMode ? "#ff4d94" : "#c00063" + readonly property color nmcSyncRefreshColor: Theme.darkMode ? "#6677ff" : "#2238df" + readonly property color nmcTrayWindowHeaderBackgroundColor: Theme.darkMode ? "#2b2b2b" : "white" + readonly property color nmcTrayWindowHeaderTextColor: Theme.darkMode ? "white" : "black" + readonly property color nmcTrayWindowHeaderSeparatorColor: Theme.darkMode ? "#3c3c3c" : "#ededed" + readonly property color nmcTrayWindowHeaderHighlightColor: Theme.darkMode ? "#444444" : "#ededed" + readonly property color nmcMenuMoreItemsColor: Theme.darkMode ? "#3a3a3a" : "#E5E5E5" + readonly property color nmcTextInButtonColor: Theme.darkMode ? "black" : "white" + + // NMC measurements + readonly property int nmcTrayWindowWidth: variableSize(480) + readonly property int nmcTrayWindowHeight: variableSize(520) + readonly property int nmcTrayWindowAddAccountButtonHeight: 56 + readonly property int nmcTrayWindowHeaderHeight: 64 + readonly property int nmcTrayWindowItemsHeight: 48 + readonly property int nmcTrayWindowIconWidth: 20 + readonly property int nmcTrayWindowLogoWidth: 64 + readonly property int nmcTrayWindowStandardMargin: 16 + readonly property int nmcTrayWindowMenuOverlayMargin: 8 + readonly property int nmcTraySyncButtonHeight: 28 + readonly property int nmcCurrentAccountButtonWidth: 180 + readonly property int nmcMenuSubItemHeight: 42 + readonly property int nmcMenuSubItemLeftPadding: 16 + readonly property int nmcStandardRadius: 4 + readonly property int nmcListViewLeftPadding: 22 + readonly property int nmcListViewIconSize: 32 + readonly property int nmcProgressFieldTextOffset: -12 + readonly property int pixelSize: fontMetrics.font.pixelSize readonly property bool darkMode: Theme.darkMode @@ -91,7 +137,7 @@ QtObject { property int folderStateIndicatorSize: 16 property int accountLabelWidth: 128 - property int accountDropDownCaretSize: 10 + property int accountDropDownCaretSize: 18 property int accountDropDownCaretMargin: 8 property int trayFoldersMenuButtonStateIndicatorBottomOffset: 5 @@ -104,7 +150,7 @@ QtObject { property int headerButtonIconSize: 48 property int minimumActivityItemHeight: 24 - property int accountIconsMenuMargin: 7 + property int accountIconsMenuMargin: 4 property int activityLabelBaseWidth: 240 @@ -127,7 +173,7 @@ QtObject { property int accountServerAnchorsMargin: 10 property int accountLabelsSpacing: 4 property int accountsServerMargin: 6 - property int accountLabelsAnchorsMargin: 5 + property int accountLabelsAnchorsMargin: 4 property int accountLabelsLayoutMargin: 12 property int accountLabelsLayoutTopMargin: 10 diff --git a/theme/black/folder.svg b/theme/black/folder.svg index 265162634208a..b4ca23cca78ac 100644 --- a/theme/black/folder.svg +++ b/theme/black/folder.svg @@ -1,7 +1,13 @@ - - - - - + + + icon/content/folder/default@svg + + + + + + + + diff --git a/theme/close-white.svg b/theme/close-white.svg new file mode 100644 index 0000000000000..f4f3c0c23cc5e --- /dev/null +++ b/theme/close-white.svg @@ -0,0 +1,7 @@ + + + icon/action/circle-close/default@svg + + + + \ No newline at end of file diff --git a/theme/close.svg b/theme/close.svg index d4102db766da4..6949d3c95049b 100644 --- a/theme/close.svg +++ b/theme/close.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + icon/action/circle-close/default@svg + + + + diff --git a/theme/more-white.svg b/theme/more-white.svg new file mode 100644 index 0000000000000..7efdfcbc6c514 --- /dev/null +++ b/theme/more-white.svg @@ -0,0 +1,7 @@ + + + /svg/icon/action/more/default + + + + \ No newline at end of file diff --git a/theme/more.svg b/theme/more.svg index 164a1b70345f8..e2f50c80c7483 100644 --- a/theme/more.svg +++ b/theme/more.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + /svg/icon/action/more/default + + + + \ No newline at end of file diff --git a/theme/settings-white.svg b/theme/settings-white.svg new file mode 100644 index 0000000000000..9004d38106663 --- /dev/null +++ b/theme/settings-white.svg @@ -0,0 +1,7 @@ + + + /svg/icon/service/settings/default + + + + \ No newline at end of file diff --git a/theme/settings.svg b/theme/settings.svg index a9c68e4067248..434caf275d458 100644 --- a/theme/settings.svg +++ b/theme/settings.svg @@ -1,7 +1,7 @@ - - - - - + + + /svg/icon/service/settings/default + + - + \ No newline at end of file diff --git a/theme/white/folder.svg b/theme/white/folder.svg index 68606b40cf8e7..393127d142233 100644 --- a/theme/white/folder.svg +++ b/theme/white/folder.svg @@ -1,7 +1,13 @@ - - - - - + + + icon/content/folder/default@svg + + + + + + + + - + \ No newline at end of file