diff --git a/Makefile b/Makefile
index da99e87..cd958ed 100644
--- a/Makefile
+++ b/Makefile
@@ -291,7 +291,9 @@ run-debug:
PROTONMAIL_ENV=dev dlv debug --build-flags "${BUILD_FLAGS}" cmd/${TARGET_CMD}/main.go -- ${RUN_FLAGS}
run-qml-preview:
- $(MAKE) -C internal/frontend/qt -f Makefile.local qmlpreview
+ find internal/frontend/qml/ -iname '*qmlc' | xargs rm -f
+ cd internal/frontend/qml/ && qmlscene -verbose -I . -f Bridge_test.qml
+
clean-frontend-qt:
# TODO: $(MAKE) -C internal/frontend/qt -f Makefile.local clean
diff --git a/internal/frontend/qml/Bridge.qml b/internal/frontend/qml/Bridge.qml
new file mode 100644
index 0000000..382774a
--- /dev/null
+++ b/internal/frontend/qml/Bridge.qml
@@ -0,0 +1,64 @@
+// Copyright (c) 2021 Proton Technologies AG
+//
+// This file is part of ProtonMail Bridge.
+//
+// ProtonMail Bridge is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// ProtonMail Bridge is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with ProtonMail Bridge. If not, see .
+
+import QtQuick 2.13
+import QtQuick.Window 2.13
+import Qt.labs.platform 1.0
+
+QtObject {
+ // default property list children: []
+
+ property var _mainWindow: MainWindow {
+ id: mainWindow
+ title: "ProtonMail Bridge"
+ visible: false
+ }
+
+ property var _trayMenu: Window {
+ id: trayMenu
+ title: "window 2"
+ visible: false
+ flags: Qt.Dialog
+
+ width: 448
+ }
+
+ property var _trayIcon: SystemTrayIcon {
+ id: trayIcon
+ visible: true
+ iconSource: "./icons/rectangle-systray.png"
+ onActivated: {
+ switch (reason) {
+ case SystemTrayIcon.Unknown:
+ break;
+ case SystemTrayIcon.Context:
+ break
+ case SystemTrayIcon.DoubleClick:
+ break
+ case SystemTrayIcon.Trigger:
+ trayMenu.x = (Screen.desktopAvailableWidth - trayMenu.width) / 2
+ trayMenu.visible = !trayMenu.visible
+ break;
+ case SystemTrayIcon.MiddleClick:
+ mainWindow.visible = !mainWindow.visible
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/internal/frontend/qml/Bridge_test.qml b/internal/frontend/qml/Bridge_test.qml
new file mode 100644
index 0000000..b772401
--- /dev/null
+++ b/internal/frontend/qml/Bridge_test.qml
@@ -0,0 +1,56 @@
+// Copyright (c) 2021 Proton Technologies AG
+//
+// This file is part of ProtonMail Bridge.
+//
+// ProtonMail Bridge is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// ProtonMail Bridge is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with ProtonMail Bridge. If not, see .
+
+import QtQuick 2.13
+import QtQuick.Window 2.13
+import QtQuick.Controls 2.13
+
+Window {
+ id: testroot
+ width : 250
+ height : 600
+ flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint
+ visible : true
+ title : "GUI test Window"
+ color : "#10101010"
+
+ Column {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing : 5
+ Button {
+ text: "Show window"
+ onClicked: {
+ bridge._mainWindow.visible = true
+ }
+ }
+ Button {
+ text: "Hide window"
+ onClicked: {
+ bridge._mainWindow.visible = false
+ }
+ }
+ }
+
+ Component.onCompleted : {
+ testroot.x= 10
+ testroot.y= 100
+ bridge._mainWindow.visible = true
+ }
+
+
+ Bridge {id:bridge}
+}
diff --git a/internal/frontend/qml/MainWindow.qml b/internal/frontend/qml/MainWindow.qml
index f7e3faa..c72ca68 100644
--- a/internal/frontend/qml/MainWindow.qml
+++ b/internal/frontend/qml/MainWindow.qml
@@ -16,48 +16,35 @@
// along with ProtonMail Bridge. If not, see .
import QtQuick 2.13
-import QtQuick.Window 2.15
-import Qt.labs.platform 1.0
+import QtQuick.Window 2.13
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
-QtObject {
+import Proton 4.0
- property var _mainWindow: Window {
- id: mainWindow
- title: "window 1"
- visible: false
- }
+Window {
+ //currentStyle: Proton.Style.prominentStyle
- property var _trayMenu: Window {
- id: trayMenu
- title: "window 2"
- visible: false
- flags: Qt.Dialog
+ //Button {
+ //
+ //}
- width: 448
- }
-
- property var _trayIcon: SystemTrayIcon {
- id: trayIcon
visible: true
- iconSource: "./icons/rectangle-systray.png"
- onActivated: {
- switch (reason) {
- case SystemTrayIcon.Unknown:
- break;
- case SystemTrayIcon.Context:
- break
- case SystemTrayIcon.DoubleClick:
- break
- case SystemTrayIcon.Trigger:
- trayMenu.x = (Screen.desktopAvailableWidth - trayMenu.width) / 2
- trayMenu.visible = !trayMenu.visible
- break;
- case SystemTrayIcon.MiddleClick:
- mainWindow.visible = !mainWindow.visible
- break;
- default:
- break;
+ color: ProtonStyle.currentStyle.background_norm
+ //StackLayout {
+ // SignIn {
+ //
+ // }
+ //}
+
+ Button {
+ id: testButton1
+ text: "Test button"
+ }
+
+ Button {
+ anchors.top: testButton1.bottom
+ secondary: true
+ text: "Test button"
}
}
- }
-}
diff --git a/internal/frontend/qml/Proton/Button.qml b/internal/frontend/qml/Proton/Button.qml
new file mode 100644
index 0000000..43edbab
--- /dev/null
+++ b/internal/frontend/qml/Proton/Button.qml
@@ -0,0 +1,128 @@
+// Copyright (c) 2021 Proton Technologies AG
+//
+// This file is part of ProtonMail Bridge.
+//
+// ProtonMail Bridge is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// ProtonMail Bridge is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with ProtonMail Bridge. If not, see .
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Controls.impl 2.12
+import QtQuick.Templates 2.12 as T
+import "."
+
+T.Button {
+ property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
+
+ property alias secondary: control.flat
+ readonly property bool primary: !secondary
+ readonly property bool isIcon: control.text === ""
+
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 8
+ horizontalPadding: 16
+ spacing: 10
+
+ icon.width: 12
+ icon.height: 12
+ icon.color: control.checked || control.highlighted ? control.palette.brightText :
+ control.flat && !control.down ? (control.visualFocus ? control.palette.highlight : control.palette.windowText) : control.palette.buttonText
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: {
+ if (!secondary) {
+ // Primary colors
+ return "#FFFFFF"
+ } else {
+ // Secondary colors
+ return colorScheme.text_norm
+ }
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: 72
+ implicitHeight: 36
+ radius: 4
+ visible: !control.flat || control.down || control.checked || control.highlighted
+ color: {
+ if (!isIcon) {
+ if (!secondary) {
+ // Primary colors
+
+ if (control.down) {
+ return colorScheme.interaction_norm_active
+ }
+
+ if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
+ return colorScheme.interaction_norm_hover
+ }
+
+ return colorScheme.interaction_norm
+ } else {
+ // Secondary colors
+
+ if (control.down) {
+ return colorScheme.interaction_default_active
+ }
+
+ if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
+ return colorScheme.interaction_default_hover
+ }
+
+ return colorScheme.interaction_default
+ }
+ } else {
+ if (!secondary) {
+ // Primary icon colors
+
+ if (control.down) {
+ return colorScheme.interaction_default_active
+ }
+
+ if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
+ return colorScheme.interaction_default_hover
+ }
+
+ return colorScheme.interaction_default
+ } else {
+ // Secondary icon colors
+
+ if (control.down) {
+ return colorScheme.interaction_default_active
+ }
+
+ if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
+ return colorScheme.interaction_default_hover
+ }
+
+ return colorScheme.interaction_default
+ }
+ }
+ }
+ opacity: control.enabled ? 1.0 : 0.5
+ }
+}
diff --git a/internal/frontend/qml/Proton/ColorScheme.qml b/internal/frontend/qml/Proton/ColorScheme.qml
new file mode 100644
index 0000000..3cf677f
--- /dev/null
+++ b/internal/frontend/qml/Proton/ColorScheme.qml
@@ -0,0 +1,88 @@
+// Copyright (c) 2021 Proton Technologies AG
+//
+// This file is part of ProtonMail Bridge.
+//
+// ProtonMail Bridge is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// ProtonMail Bridge is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with ProtonMail Bridge. If not, see .
+
+import QtQml 2.13
+
+// https://wiki.qt.io/Qml_Styling
+// http://imaginativethinking.ca/make-qml-component-singleton/
+
+QtObject {
+ // Primary
+ property color primay_norm
+
+ // Interaction-norm
+ property color interaction_norm
+ property color interaction_norm_hover
+ property color interaction_norm_active
+
+ // Text
+ property color text_norm
+ property color text_weak
+ property color text_hint
+ property color text_disabled
+ property color text_invert
+
+ // Field
+ property color field_norm
+ property color field_hover
+ property color field_disabled
+
+ // Border
+ property color border_norm
+ property color border_weak
+
+ // Background
+ property color background_norm
+ property color background_weak
+ property color background_strong
+ property color background_avatar
+
+ // Interaction-weak
+ property color interaction_weak
+ property color interaction_weak_hover
+ property color interaction_weak_active
+
+ // Interaction-default
+ property color interaction_default
+ property color interaction_default_hover
+ property color interaction_default_active
+
+ // Scrollbar
+ property color scrollbar_norm
+ property color scrollbar_hover
+
+ // Signal
+ property color signal_danger
+ property color signal_danger_hover
+ property color signal_danger_active
+ property color signal_warning
+ property color signal_warning_hover
+ property color signal_warning_active
+ property color signal_success
+ property color signal_success_hover
+ property color signal_success_active
+ property color signal_info
+ property color signal_info_hover
+ property color signal_info_active
+
+ // Shadows
+ property color shadow_norm
+ property color shadow_lifted
+
+ // Backdrop
+ property color backdrop_norm
+}
diff --git a/internal/frontend/qml/Proton/Style.qml b/internal/frontend/qml/Proton/Style.qml
new file mode 100644
index 0000000..2284055
--- /dev/null
+++ b/internal/frontend/qml/Proton/Style.qml
@@ -0,0 +1,302 @@
+// Copyright (c) 2021 Proton Technologies AG
+//
+// This file is part of ProtonMail Bridge.
+//
+// ProtonMail Bridge is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// ProtonMail Bridge is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with ProtonMail Bridge. If not, see .
+
+pragma Singleton
+import QtQml 2.13
+
+import "./"
+
+// https://wiki.qt.io/Qml_Styling
+// http://imaginativethinking.ca/make-qml-component-singleton/
+
+QtObject {
+
+ // TODO: Once we will use Qt >=5.15 this should be refactored with inline components as follows:
+ // https://doc.qt.io/qt-5/qtqml-documents-definetypes.html#inline-components
+
+ //component ColorScheme: QtObject {
+ // property color primay_norm
+ // ...
+ //}
+
+ // and instead of "var" later on "ColorScheme" should be used
+
+ property var _lightStyle: ColorScheme {
+ id: lightStyle
+
+ // Primary
+ primay_norm: "#657EE4"
+
+ // Interaction-norm
+ interaction_norm: "#657EE4"
+ interaction_norm_hover: "#5064B6"
+ interaction_norm_active: "#3C4B88"
+
+ // Text
+ text_norm: "#262A33"
+ text_weak: "#696F7D"
+ text_hint: "#A4A9B5"
+ text_disabled: "#BABEC7"
+ text_invert: "#FFFFFF"
+
+ // Field
+ field_norm: "#BABEC7"
+ field_hover: "#A4A9B5"
+ field_disabled: "#D0D3DA"
+
+ // Border
+ border_norm: "#D0D3DA"
+ border_weak: "#E7E9EC"
+
+ // Background
+ background_norm: "#FFFFFF"
+ background_weak: "#F3F4F6"
+ background_strong: "#E7E9EC"
+ background_avatar: "#A4A9B5"
+
+ // Interaction-weak
+ interaction_weak: "#D0D3DA"
+ interaction_weak_hover: "#BABEC7"
+ interaction_weak_active: "#A4A9B5"
+
+ // Interaction-default
+ interaction_default: "#00000000"
+ interaction_default_hover: "#33BABEC7"
+ interaction_default_active: "#4DBABEC7"
+
+ // Scrollbar
+ scrollbar_norm: "#D0D3DA"
+ scrollbar_hover: "#BABEC7"
+
+ // Signal
+ signal_danger: "#D42F34"
+ signal_danger_hover: "#C7262B"
+ signal_danger_active: "#BA1E23"
+ signal_warning: "#F5830A"
+ signal_warning_hover: "#F5740A"
+ signal_warning_active: "#F5640A"
+ signal_success: "#1B8561"
+ signal_success_hover: "#147857"
+ signal_success_active: "#0F6B4C"
+ signal_info: "#1578CF"
+ signal_info_hover: "#0E6DC2"
+ signal_info_active: "#0764B5"
+
+ // Shadows
+ shadow_norm: "#FFFFFF"
+ shadow_lifted: "#FFFFFF"
+
+ // Backdrop
+ backdrop_norm: "#7A262A33"
+ }
+
+ property var _prominentStyle: ColorScheme {
+ id: prominentStyle
+
+ // Primary
+ primay_norm: "#657EE4"
+
+ // Interaction-norm
+ interaction_norm: "#657EE4"
+ interaction_norm_hover: "#7D92E8"
+ interaction_norm_active: "#98A9EE"
+
+ // Text
+ text_norm: "#FFFFFF"
+ text_weak: "#949BB9"
+ text_hint: "#565F84"
+ text_disabled: "#444E72"
+ text_invert: "#1C223D"
+
+ // Field
+ field_norm: "#565F84"
+ field_hover: "#949BB9"
+ field_disabled: "#353E60"
+
+ // Border
+ border_norm: "#353E60"
+ border_weak: "#2D3657"
+
+ // Background
+ background_norm: "#1C223D"
+ background_weak: "#272F4F"
+ background_strong: "#2D3657"
+ background_avatar: "#444E72"
+
+ // Interaction-weak
+ interaction_weak: "#353E60"
+ interaction_weak_hover: "#444E72"
+ interaction_weak_active: "#565F84"
+
+ // Interaction-default
+ interaction_default: "#00000000"
+ interaction_default_hover: "#4D444E72"
+ interaction_default_active: "#66444E72"
+
+ // Scrollbar
+ scrollbar_norm: "#353E60"
+ scrollbar_hover: "#444E72"
+
+ // Signal
+ signal_danger: "#ED4C51"
+ signal_danger_hover: "#F7595E"
+ signal_danger_active: "#FF666B"
+ signal_warning: "#F5930A"
+ signal_warning_hover: "#F5A716"
+ signal_warning_active: "#F5B922"
+ signal_success: "#349172"
+ signal_success_hover: "#339C79"
+ signal_success_active: "#31A67F"
+ signal_info: "#2C89DB"
+ signal_info_hover: "#3491E3"
+ signal_info_active: "#3D99EB"
+
+ // Shadows
+ shadow_norm: "#1C223D"
+ shadow_lifted: "#1C223D"
+
+ // Backdrop
+ backdrop_norm: "#52000000"
+ }
+
+ property var _darkStyle: ColorScheme {
+ id: darkStyle
+
+ // Primary
+ primay_norm: "#657EE4"
+
+ // Interaction-norm
+ interaction_norm: "#657EE4"
+ interaction_norm_hover: "#7D92E8"
+ interaction_norm_active: "#98A9EE"
+
+ // Text
+ text_norm: "#FFFFFF"
+ text_weak: "#A4A9B5"
+ text_hint: "#696F7D"
+ text_disabled: "#575D6B"
+ text_invert: "#262A33"
+
+ // Field
+ field_norm: "#575D6B"
+ field_hover: "#696F7D"
+ field_disabled: "#464B58"
+
+ // Border
+ border_norm: "#464B58"
+ border_weak: "#363A46"
+
+ // Background
+ background_norm: "#262A33"
+ background_weak: "#2E323C"
+ background_strong: "#363A46"
+ background_avatar: "#575D6B"
+
+ // Interaction-weak
+ interaction_weak: "#464B58"
+ interaction_weak_hover: "#575D6B"
+ interaction_weak_active: "#696F7D"
+
+ // Interaction-default
+ interaction_default: "#00000000"
+ interaction_default_hover: "#33575D6B"
+ interaction_default_active: "#4D575D6B"
+
+ // Scrollbar
+ scrollbar_norm: "#464B58"
+ scrollbar_hover: "#575D6B"
+
+ // Signal
+ signal_danger: "#ED4C51"
+ signal_danger_hover: "#F7595E"
+ signal_danger_active: "#FF666B"
+ signal_warning: "#F5930A"
+ signal_warning_hover: "#F5A716"
+ signal_warning_active: "#F5B922"
+ signal_success: "#349172"
+ signal_success_hover: "#339C79"
+ signal_success_active: "#31A67F"
+ signal_info: "#2C89DB"
+ signal_info_hover: "#3491E3"
+ signal_info_active: "#3D99EB"
+
+ // Shadows
+ shadow_norm: "#262A33"
+ shadow_lifted: "#262A33"
+
+ // Backdrop
+ backdrop_norm: "#52000000"
+ }
+
+ // TODO: if default style should be loaded from somewhere - it should be loaded here
+ property var currentStyle: lightStyle
+
+ property var _timer: Timer {
+ interval: 1000
+ repeat: true
+ running: true
+ onTriggered: {
+ switch (currentStyle) {
+ case lightStyle:
+ console.debug("Dark Style")
+ currentStyle = darkStyle
+ return
+ case darkStyle:
+ console.debug("Prominent Style")
+ currentStyle = prominentStyle
+ return
+ case prominentStyle:
+ console.debug("Light Style")
+ currentStyle = lightStyle
+ return
+ }
+ }
+ }
+
+
+
+ property string font: {
+ // TODO: add OS to backend
+ return "Ubuntu"
+
+ //switch (backend.OS) {
+ // case "Windows":
+ // return "Segoe UI"
+ // case "OSX":
+ // return "SF Pro Display"
+ // case "Linux":
+ // return "Ubuntu"
+ //}
+ }
+
+ property int heading_font_size: 28
+ property int heading_line_height: 36
+
+ property int title_font_size: 20
+ property int title_line_height: 24
+
+ property int lead_font_size: 18
+ property int lead_line_height: 26
+
+ property int body_font_size: 14
+ property int body_line_height: 20
+ property real body_letter_spacing: 0.2
+
+ property int caption_font_size: 12
+ property int caption_line_height: 16
+ property real caption_letter_spacing: 0.4
+ }
diff --git a/internal/frontend/qml/Proton/qmldir b/internal/frontend/qml/Proton/qmldir
new file mode 100644
index 0000000..d518f67
--- /dev/null
+++ b/internal/frontend/qml/Proton/qmldir
@@ -0,0 +1,6 @@
+module QQtQuick.Controls.Proton
+depends QtQuick.Controls 2.12
+
+singleton ProtonStyle 4.0 Style.qml
+Button 4.0 Button.qml
+
diff --git a/internal/frontend/qml/qtquickcontrols2.conf b/internal/frontend/qml/qtquickcontrols2.conf
new file mode 100644
index 0000000..3512d51
--- /dev/null
+++ b/internal/frontend/qml/qtquickcontrols2.conf
@@ -0,0 +1,2 @@
+[Controls]
+Style=Proton