From e0d07d67a033d5bb146474129846049eb10bd79a Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 9 Aug 2021 14:40:56 +0200 Subject: [PATCH] GODT-22: Frontend-backend - GODT-1246 Implement settings view. - GODT-1257 GODT-1246: Account and Help view - GODT-1298: Minimal working build (panics) - GODT-1298: loading QML (needs Popup window) - GODT-1298: WARN: Adding PopupWindow not possible! In therecipe qt the `quickwidgets` classes are within `quick` module, but forgot to add library and include paths into cgo flags. Therefore compilation fails and it would be hard to patch therecipe in order to fix it. I am not sure if rewrite PopupWindow into go would make any difference, therefore I decided to use normal QML Window without borders. - GODT-1298: Rework status window, add backend props, slots and signals. - GODT-1298: Users - GODT-1298: Login - GODT-1298: WIP Help and bug report - GODT-1178: MacOS dock icon control - GODT-1298: Help, bug report, update and events - GODT-1298: Apple Mail config and Settings (without cache on disk) --- .gitignore | 33 +- .gitlab-ci.yml | 2 + .golangci.yml | 2 - Makefile | 16 +- go.mod | 4 +- go.sum | 18 +- internal/frontend/.gitignore | 11 + internal/frontend/Makefile.local | 14 + internal/frontend/clientconfig/config.go | 76 ++++ .../frontend/clientconfig/config_applemail.go | 121 ++++++ internal/frontend/frontend.go | 18 + internal/frontend/qml/AccountDelegate.qml | 144 ++++++- internal/frontend/qml/AccountView.qml | 241 ++++++++++- internal/frontend/qml/Banner.qml | 38 +- internal/frontend/qml/Bridge.qml | 158 ++++--- .../frontend/qml/BridgeTest/UserControl.qml | 47 +++ internal/frontend/qml/Bridge_test.qml | 364 +++++++++++++--- internal/frontend/qml/BugReportView.qml | 167 ++++++++ internal/frontend/qml/Configuration.qml | 73 ++++ internal/frontend/qml/ConfigurationItem.qml | 81 ++++ internal/frontend/qml/ContentWrapper.qml | 165 +++++++- internal/frontend/qml/GeneralSettings.qml | 168 ++++++++ internal/frontend/qml/HelpView.qml | 110 +++++ internal/frontend/qml/LocalCacheSettings.qml | 146 +++++++ internal/frontend/qml/MainWindow.qml | 39 +- internal/frontend/qml/NotificationDialog.qml | 13 +- internal/frontend/qml/NotificationPopups.qml | 28 +- .../qml/Notifications/Notification.qml | 1 + .../qml/Notifications/Notifications.qml | 391 ++++++++++++++++-- internal/frontend/qml/PortSettings.qml | 154 +++++++ internal/frontend/qml/Proton/Button.qml | 18 +- .../frontend/qml/Proton/RoundedRectangle.qml | 2 +- internal/frontend/qml/Proton/TextArea.qml | 28 +- internal/frontend/qml/Proton/Toggle.qml | 107 +++++ internal/frontend/qml/Proton/qmldir | 1 + internal/frontend/qml/SMTPSettings.qml | 120 ++++++ internal/frontend/qml/SettingsItem.qml | 105 +++++ internal/frontend/qml/SettingsView.qml | 71 ++++ internal/frontend/qml/SetupGuide.qml | 60 ++- internal/frontend/qml/SignIn.qml | 48 +-- internal/frontend/qml/StatusWindow.qml | 44 +- internal/frontend/qml/WelcomeGuide.qml | 2 +- .../frontend/qml/icons/ic-chevron-down.svg | 5 + internal/frontend/qml/icons/ic-chevron-up.svg | 5 + internal/frontend/qml/icons/ic-copy.svg | 4 + .../frontend/qml/icons/ic-external-link.svg | 3 + internal/frontend/qml/icons/ic-info.svg | 12 + internal/frontend/qml/icons/ic-trash.svg | 5 + internal/frontend/qt/dockicon/DockIcon.h | 24 ++ internal/frontend/qt/dockicon/DockIcon.m | 42 ++ .../frontend/qt/dockicon/dockicon_darwin.go | 33 ++ .../frontend/qt/dockicon/dockicon_default.go | 26 ++ internal/frontend/qt/frontend.go | 146 +++++++ internal/frontend/qt/frontend_events.go | 85 ++++ internal/frontend/qt/frontend_help.go | 45 ++ internal/frontend/qt/frontend_init.go | 71 ++++ internal/frontend/qt/frontend_nogui.go | 83 ++++ internal/frontend/qt/frontend_settings.go | 151 +++++++ internal/frontend/qt/frontend_updates.go | 130 ++++++ internal/frontend/qt/frontend_users.go | 224 ++++++++++ internal/frontend/qt/helpers.go | 70 ++++ internal/frontend/qt/log/log.cpp | 44 ++ internal/frontend/qt/log/log.go | 46 +++ internal/frontend/qt/log/log.h | 36 ++ internal/frontend/qt/qml_backend.go | 203 +++++++++ internal/frontend/qt/qml_users.go | 135 ++++++ internal/frontend/share/Bridge.icns | Bin 0 -> 266570 bytes internal/frontend/share/logo.ico | Bin 0 -> 569990 bytes internal/frontend/share/logo.svg | 31 ++ internal/users/user.go | 4 +- internal/users/user_credentials_test.go | 5 + internal/users/user_new_test.go | 2 +- internal/users/users.go | 1 + internal/users/users_clear_test.go | 3 + internal/users/users_delete_test.go | 4 + internal/users/users_new_test.go | 1 + 76 files changed, 4730 insertions(+), 398 deletions(-) create mode 100644 internal/frontend/.gitignore create mode 100644 internal/frontend/Makefile.local create mode 100644 internal/frontend/clientconfig/config.go create mode 100644 internal/frontend/clientconfig/config_applemail.go create mode 100644 internal/frontend/qml/BugReportView.qml create mode 100644 internal/frontend/qml/Configuration.qml create mode 100644 internal/frontend/qml/ConfigurationItem.qml create mode 100644 internal/frontend/qml/GeneralSettings.qml create mode 100644 internal/frontend/qml/HelpView.qml create mode 100644 internal/frontend/qml/LocalCacheSettings.qml create mode 100644 internal/frontend/qml/PortSettings.qml create mode 100644 internal/frontend/qml/Proton/Toggle.qml create mode 100644 internal/frontend/qml/SMTPSettings.qml create mode 100644 internal/frontend/qml/SettingsItem.qml create mode 100644 internal/frontend/qml/SettingsView.qml create mode 100644 internal/frontend/qml/icons/ic-chevron-down.svg create mode 100644 internal/frontend/qml/icons/ic-chevron-up.svg create mode 100644 internal/frontend/qml/icons/ic-copy.svg create mode 100644 internal/frontend/qml/icons/ic-external-link.svg create mode 100644 internal/frontend/qml/icons/ic-info.svg create mode 100644 internal/frontend/qml/icons/ic-trash.svg create mode 100644 internal/frontend/qt/dockicon/DockIcon.h create mode 100644 internal/frontend/qt/dockicon/DockIcon.m create mode 100644 internal/frontend/qt/dockicon/dockicon_darwin.go create mode 100644 internal/frontend/qt/dockicon/dockicon_default.go create mode 100644 internal/frontend/qt/frontend.go create mode 100644 internal/frontend/qt/frontend_events.go create mode 100644 internal/frontend/qt/frontend_help.go create mode 100644 internal/frontend/qt/frontend_init.go create mode 100644 internal/frontend/qt/frontend_nogui.go create mode 100644 internal/frontend/qt/frontend_settings.go create mode 100644 internal/frontend/qt/frontend_updates.go create mode 100644 internal/frontend/qt/frontend_users.go create mode 100644 internal/frontend/qt/helpers.go create mode 100644 internal/frontend/qt/log/log.cpp create mode 100644 internal/frontend/qt/log/log.go create mode 100644 internal/frontend/qt/log/log.h create mode 100644 internal/frontend/qt/qml_backend.go create mode 100644 internal/frontend/qt/qml_users.go create mode 100644 internal/frontend/share/Bridge.icns create mode 100644 internal/frontend/share/logo.ico create mode 100644 internal/frontend/share/logo.svg diff --git a/.gitignore b/.gitignore index d516050d..c5816869 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,6 @@ .*.sw? *~ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -vendor - # Test files godog.test debug.test @@ -17,17 +14,12 @@ coverage.html # Run files mem.pprof -# Auto generated frontend -internal/frontend/qml/BridgeUI/*.qmlc -internal/frontend/qml/ImportExportUI/*.qmlc -internal/frontend/qml/ProtonUI/*.qmlc -internal/frontend/qml/ProtonUI/fontawesome.ttf -internal/frontend/qml/ProtonUI/images -internal/frontend/qml/ImportExportUI/images -frontend/qml/*.qmlc - -# Credits files (generated). +# Auto generated internal/**/credits.go +vendor +vendor-cache +/main.go + # Build files /launcher-* @@ -37,18 +29,3 @@ internal/**/credits.go /hasher cmd/Desktop-Bridge/deploy cmd/Import-Export/deploy -internal/frontend/qt*/moc.cpp -internal/frontend/qt*/moc.go -internal/frontend/qt*/moc.h -internal/frontend/qt*/moc_cgo_*.go -internal/frontend/qt*/moc_moc.h -internal/frontend/qt*/rcc.cpp -internal/frontend/qt*/rcc.qrc -internal/frontend/qt*/rcc_cgo_*.go - -internal/frontend/rcc.cpp -internal/frontend/rcc.qrc -internal/frontend/rcc_cgo_*.go -vendor-cache/ - -/main.go diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 48b6aea2..3c54b00b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -126,6 +126,7 @@ build-linux-qa: extends: .build-base only: - web + - branches script: - BUILD_TAGS="build_qa" make build artifacts: @@ -161,6 +162,7 @@ build-darwin-qa: extends: .build-darwin-base only: - web + - branches script: - BUILD_TAGS="build_qa" make build artifacts: diff --git a/.golangci.yml b/.golangci.yml index 799d2645..ebaab17f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,6 @@ --- run: timeout: 10m - build-tags: - - nogui skip-dirs: - pkg/mime diff --git a/Makefile b/Makefile index 288eead8..6e2b2ff6 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ ${TGZ_TARGET}: ${DEPLOY_DIR}/${TARGET_OS} cd ${DEPLOY_DIR}/${TARGET_OS} && tar czf ../../../../$@ . ${DEPLOY_DIR}/linux: ${EXE_TARGET} - cp -pf ./internal/frontend/share/icons/${SRC_SVG} ${DEPLOY_DIR}/linux/logo.svg + cp -pf ./internal/frontend/share/${SRC_SVG} ${DEPLOY_DIR}/linux/logo.svg cp -pf ./LICENSE ${DEPLOY_DIR}/linux/ cp -pf ./Changelog.md ${DEPLOY_DIR}/linux/ cp -pf ./dist/${EXE_NAME}.desktop ${DEPLOY_DIR}/linux/ @@ -98,7 +98,7 @@ ${DEPLOY_DIR}/darwin: ${EXE_TARGET} mv ${EXE_TARGET}/Contents/MacOS/{${DIRNAME},${EXE_NAME}}; \ perl -i -pe"s/>${DIRNAME}/>${EXE_NAME}/g" ${EXE_TARGET}/Contents/Info.plist; \ fi - cp ./internal/frontend/share/icons/${SRC_ICNS} ${DARWINAPP_CONTENTS}/Resources/${SRC_ICNS} + cp ./internal/frontend/share/${SRC_ICNS} ${DARWINAPP_CONTENTS}/Resources/${SRC_ICNS} cp LICENSE ${DARWINAPP_CONTENTS}/Resources/ rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebEngine.framework" rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebView.framework" @@ -106,7 +106,7 @@ ${DEPLOY_DIR}/darwin: ${EXE_TARGET} ./utils/remove_non_relative_links_darwin.sh "${EXE_TARGET}${EXE_BINARY_DARWIN}" ${DEPLOY_DIR}/windows: ${EXE_TARGET} - cp ./internal/frontend/share/icons/${SRC_ICO} ${DEPLOY_DIR}/windows/logo.ico + cp ./internal/frontend/share/${SRC_ICO} ${DEPLOY_DIR}/windows/logo.ico cp LICENSE ${DEPLOY_DIR}/windows/ QT_BUILD_TARGET:=build desktop @@ -127,9 +127,9 @@ ${EXE_TARGET}: check-has-go gofiles ${RESOURCE_FILE} ${VENDOR_TARGET} WINDRES_YEAR:=$(shell date +%Y) APP_VERSION_COMMA:=$(shell echo "${APP_VERSION}" | sed -e 's/[^0-9,.]*//g' -e 's/\./,/g') -resource.syso: ./internal/frontend/share/info.rc ./internal/frontend/share/icons/${SRC_ICO} .FORCE +resource.syso: ./internal/frontend/share/info.rc ./internal/frontend/share/${SRC_ICO} .FORCE rm -f ./*.syso - windres --target=pe-x86-64 -I ./internal/frontend/share/icons/ -D ICO_FILE=${SRC_ICO} -D EXE_NAME="${EXE_NAME}" -D FILE_VERSION="${APP_VERSION}" -D ORIGINAL_FILE_NAME="${EXE}" -D PRODUCT_VERSION="${APP_VERSION}" -D FILE_VERSION_COMMA=${APP_VERSION_COMMA} -D YEAR=${WINDRES_YEAR} -o $@ $< + windres --target=pe-x86-64 -I ./internal/frontend/share/ -D ICO_FILE=${SRC_ICO} -D EXE_NAME="${EXE_NAME}" -D FILE_VERSION="${APP_VERSION}" -D ORIGINAL_FILE_NAME="${EXE}" -D PRODUCT_VERSION="${APP_VERSION}" -D FILE_VERSION_COMMA=${APP_VERSION_COMMA} -D YEAR=${WINDRES_YEAR} -o $@ $< ## Rules for therecipe/qt .PHONY: prepare-vendor update-vendor update-qt-docs @@ -278,7 +278,7 @@ RUN_FLAGS?=-m -l=${LOG} --log-imap=${LOG_IMAP} ${LOG_SMTP} run: run-nogui-cli run-qt: ${EXE_TARGET} - PROTONMAIL_ENV=dev ./$< ${RUN_FLAGS} | tee last.log + PROTONMAIL_ENV=dev ./$< ${RUN_FLAGS} 2>&1 | tee last.log run-qt-cli: ${EXE_TARGET} PROTONMAIL_ENV=dev ./$< ${RUN_FLAGS} -c @@ -296,9 +296,7 @@ run-qml-preview: clean-frontend-qt: - # TODO: $(MAKE) -C internal/frontend/qt -f Makefile.local clean -clean-frontend-qt-common: - # TODO: $(MAKE) -C internal/frontend/qt-common -f Makefile.local clean + $(MAKE) -C internal/frontend -f Makefile.local clean clean-vendor: clean-frontend-qt clean-frontend-qt-common rm -rf ./vendor diff --git a/go.mod b/go.mod index d1a5df19..fc5873c4 100644 --- a/go.mod +++ b/go.mod @@ -56,8 +56,10 @@ require ( github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 github.com/sirupsen/logrus v1.7.0 github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect - github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.7.0 + github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e + github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d // indirect + github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d // indirect github.com/urfave/cli/v2 v2.2.0 github.com/vmihailenco/msgpack/v5 v5.1.3 go.etcd.io/bbolt v1.3.6 diff --git a/go.sum b/go.sum index a4c5597d..22599e10 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,6 @@ github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1 github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-rfc5322 v0.8.0 h1:7emrf75n3CDIduQflx7aT1nJa5h/kGsiFKUYX/+IAkU= github.com/ProtonMail/go-rfc5322 v0.8.0/go.mod h1:BwpTbkJxkMGkc+pC84AXZnwuWOisEULBpfPIyIKS/Us= -github.com/ProtonMail/go-srp v0.0.0-20210910093455-a843a0b9adff h1:eiue56XAPSkOpsy5Fwnyz4+Vd7i2cN5D4orc++Irt1g= -github.com/ProtonMail/go-srp v0.0.0-20210910093455-a843a0b9adff/go.mod h1:Uvv5cqSGCs8MTZ8sbKiCkBnaB6/OA3eq2mc77tl2VVA= github.com/ProtonMail/go-srp v0.0.1 h1:J0O9Zb5XTC6iDrB7feH41cu+TUEB+l7uHctXIK6oS2o= github.com/ProtonMail/go-srp v0.0.1/go.mod h1:Uvv5cqSGCs8MTZ8sbKiCkBnaB6/OA3eq2mc77tl2VVA= github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5 h1:Uga1DHFN4GUxuDQr0F71tpi8I9HqPIlZodZAI1lR6VQ= @@ -195,6 +193,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e h1:XWcjeEtTFTOVA9Fs1w7n2XBftk5ib4oZrhzWk0B+3eA= +github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -264,6 +264,7 @@ github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -361,9 +362,11 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -393,6 +396,12 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e h1:G0DQ/TRQyrEZjtLlLwevFjaRiG8eeCMlq9WXQ2OO2bk= +github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us= +github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d h1:hAZyEG2swPRWjF0kqqdGERXUazYnRJdAk4a58f14z7Y= +github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d/go.mod h1:7m8PDYDEtEVqfjoUQc2UrFqhG0CDmoVJjRlQxexndFc= +github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d h1:AJRoBel/g9cDS+yE8BcN3E+TDD/xNAguG21aoR8DAIE= +github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d/go.mod h1:mH55Ek7AZcdns5KPp99O0bg+78el64YCYWHiQKrOdt4= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -430,6 +439,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -473,6 +483,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -505,7 +516,9 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -539,6 +552,7 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= diff --git a/internal/frontend/.gitignore b/internal/frontend/.gitignore new file mode 100644 index 00000000..e2c7a202 --- /dev/null +++ b/internal/frontend/.gitignore @@ -0,0 +1,11 @@ +# Auto generated +moc.cpp +moc.go +moc.h +moc_cgo_*.go +moc_moc.h +rcc.cpp +rcc.qrc +rcc_cgo_*.go +*.qmlc + diff --git a/internal/frontend/Makefile.local b/internal/frontend/Makefile.local new file mode 100644 index 00000000..0bd5369f --- /dev/null +++ b/internal/frontend/Makefile.local @@ -0,0 +1,14 @@ +FILES=$(shell find . -iname 'rcc.qrc') +FILES+=$(shell find . -iname 'rcc.cpp') +FILES+=$(shell find . -iname 'rcc_cgo*.go') + +FILES+=$(shell find . -iname 'moc.go') +FILES+=$(shell find . -iname 'moc.cpp') +FILES+=$(shell find . -iname 'moc.h') +FILES+=$(shell find . -iname 'moc_cgo*.go') + +FILES+=$(shell find ./qml -iname '*.qmlc') + +clean: + rm -f ${FILES} + diff --git a/internal/frontend/clientconfig/config.go b/internal/frontend/clientconfig/config.go new file mode 100644 index 00000000..5495c3a9 --- /dev/null +++ b/internal/frontend/clientconfig/config.go @@ -0,0 +1,76 @@ +// 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 . + +// Package clientconfig provides automatic config of IMAP and SMTP. +// For now only for Apple Mail. +package clientconfig + +import ( + "errors" + + "github.com/ProtonMail/proton-bridge/internal/config/settings" + "github.com/ProtonMail/proton-bridge/internal/config/useragent" + "github.com/ProtonMail/proton-bridge/internal/frontend/types" + "github.com/sirupsen/logrus" +) + +type AutoConfig interface { + Name() string + Configure(imapPort int, smtpPort int, imapSSl, smtpSSL bool, user types.User, address string) error +} + +var ( + available = map[string]AutoConfig{} //nolint[gochecknoglobals] + ErrNotAvailable = errors.New("configuration not available") +) + +const AppleMailClient = "Apple Mail" + +func ConfigureAppleMail(user types.User, address string, s *settings.Settings) (needRestart bool, err error) { + return configure(AppleMailClient, user, address, s) +} + +func configure(configName string, user types.User, address string, s *settings.Settings) (needRestart bool, err error) { + log := logrus.WithField("pkg", "client_config").WithField("client", configName) + + config, ok := available[configName] + if !ok { + return false, ErrNotAvailable + } + + imapPort := s.GetInt(settings.IMAPPortKey) + imapSSL := false + smtpPort := s.GetInt(settings.SMTPPortKey) + smtpSSL := s.GetBool(settings.SMTPSSLKey) + + if address == "" { + address = user.GetPrimaryAddress() + } + + if configName == AppleMailClient { + // If configuring apple mail for Catalina or newer, users should use SSL. + needRestart = false + if !smtpSSL && useragent.IsCatalinaOrNewer() { + smtpSSL = true + s.SetBool(settings.SMTPSSLKey, true) + log.Warn("Detected Catalina or newer with bad SMTP SSL settings, now using SSL, bridge needs to restart") + needRestart = true + } + } + + return needRestart, config.Configure(imapPort, smtpPort, imapSSL, smtpSSL, user, address) +} diff --git a/internal/frontend/clientconfig/config_applemail.go b/internal/frontend/clientconfig/config_applemail.go new file mode 100644 index 00000000..561817b0 --- /dev/null +++ b/internal/frontend/clientconfig/config_applemail.go @@ -0,0 +1,121 @@ +// 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 . + +// +build darwin + +package clientconfig + +import ( + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/ProtonMail/proton-bridge/internal/bridge" + "github.com/ProtonMail/proton-bridge/internal/config/useragent" + "github.com/ProtonMail/proton-bridge/internal/frontend/types" + "github.com/ProtonMail/proton-bridge/pkg/mobileconfig" +) + +const ( + bigSurPreferncesPane = "/System/Library/PreferencePanes/Profiles.prefPane" +) + +func init() { //nolint[gochecknoinit] + available[AppleMailClient] = &appleMail{} +} + +type appleMail struct{} + +func (c *appleMail) Name() string { return AppleMailClient } + +func (c *appleMail) Configure(imapPort, smtpPort int, imapSSL, smtpSSL bool, user types.User, address string) error { + mc := prepareMobileConfig(imapPort, smtpPort, imapSSL, smtpSSL, user, address) + + confPath, err := saveConfigTemporarily(mc) + if err != nil { + return err + } + + if useragent.IsBigSurOrNewer() { + return exec.Command("open", bigSurPreferncesPane, confPath).Run() //nolint[gosec] G204: open command is safe, mobileconfig is generated by us + } + + return exec.Command("open", confPath).Run() //nolint[gosec] G204: open command is safe, mobileconfig is generated by us +} + +func prepareMobileConfig(imapPort, smtpPort int, imapSSL, smtpSSL bool, user types.User, address string) *mobileconfig.Config { + displayName := address + addresses := address + + if user.IsCombinedAddressMode() { + displayName = user.GetPrimaryAddress() + addresses = strings.Join(user.GetAddresses(), ",") + } + + timestamp := strconv.FormatInt(time.Now().Unix(), 10) + + return &mobileconfig.Config{ + EmailAddress: addresses, + DisplayName: displayName, + Identifier: "protonmail " + displayName + timestamp, + IMAP: &mobileconfig.IMAP{ + Hostname: bridge.Host, + Port: imapPort, + TLS: imapSSL, + Username: displayName, + Password: user.GetBridgePassword(), + }, + SMTP: &mobileconfig.SMTP{ + Hostname: bridge.Host, + Port: smtpPort, + TLS: smtpSSL, + Username: displayName, + }, + } +} + +func saveConfigTemporarily(mc *mobileconfig.Config) (fname string, err error) { + dir, err := ioutil.TempDir("", "protonmail-autoconfig") + if err != nil { + return + } + + // Make sure the temporary file is deleted. + go (func() { + <-time.After(10 * time.Minute) + _ = os.RemoveAll(dir) + })() + + // Make sure the file is only readable for the current user. + fname = filepath.Clean(filepath.Join(dir, "protonmail.mobileconfig")) + f, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE, 0600) + if err != nil { + return + } + + if err = mc.WriteOut(f); err != nil { + _ = f.Close() + return + } + _ = f.Close() + + return +} diff --git a/internal/frontend/frontend.go b/internal/frontend/frontend.go index 4f7ad05a..cf15eedf 100644 --- a/internal/frontend/frontend.go +++ b/internal/frontend/frontend.go @@ -24,6 +24,7 @@ import ( "github.com/ProtonMail/proton-bridge/internal/config/settings" "github.com/ProtonMail/proton-bridge/internal/config/useragent" "github.com/ProtonMail/proton-bridge/internal/frontend/cli" + "github.com/ProtonMail/proton-bridge/internal/frontend/qt" "github.com/ProtonMail/proton-bridge/internal/frontend/types" "github.com/ProtonMail/proton-bridge/internal/locations" "github.com/ProtonMail/proton-bridge/internal/updater" @@ -59,6 +60,23 @@ func New( ) Frontend { bridgeWrap := types.NewBridgeWrap(bridge) switch frontendType { + case "qt": + return qt.New( + version, + buildVersion, + programName, + showWindowOnStart, + panicHandler, + locations, + settings, + eventListener, + updater, + userAgent, + bridgeWrap, + noEncConfirmator, + autostart, + restarter, + ) case "cli": return cli.New( panicHandler, diff --git a/internal/frontend/qml/AccountDelegate.qml b/internal/frontend/qml/AccountDelegate.qml index 4782e2ef..011565b7 100644 --- a/internal/frontend/qml/AccountDelegate.qml +++ b/internal/frontend/qml/AccountDelegate.qml @@ -27,12 +27,61 @@ Item { property ColorScheme colorScheme property var user - implicitHeight: children[0].implicitHeight - implicitWidth: children[0].implicitWidth + property var _spacing: 12 + property var _leftRightMargins: { + switch(root.type) { + case AccountDelegate.SmallView: return 12 + case AccountDelegate.LargeView: return 0 + } + } + property var _topBottomMargins: { + switch(root.type) { + case AccountDelegate.SmallView: return 10 + case AccountDelegate.LargeView: return 0 + } + } + + property color usedSpaceColor : { + if (!root.enabled) return root.colorScheme.text_weak + if (root.type == AccountDelegate.SmallView) return root.colorScheme.text_weak + if (root.usedFraction < .50) return root.colorScheme.signal_success + if (root.usedFraction < .75) return root.colorScheme.signal_warning + return root.colorScheme.signal_danger + } + property real usedFraction: root.user.totalBytes ? root.user.usedBytes / root.user.totalBytes : 0 + property string totalSpace: root.spaceWithUnits(root.user.totalBytes) + property string usedSpace: root.spaceWithUnits(root.user.usedBytes) + + function spaceWithUnits(bytes){ + if (bytes*1 !== bytes ) return "0 kB" + var units = ['B',"kB", "MB", "TB"]; + var i = parseInt(Math.floor(Math.log(bytes)/Math.log(1024))); + + return Math.round(bytes*10 / Math.pow(1024, i))/10 + " " + units[i] + } + + signal clicked() + + // width expected to be set by parent object + implicitHeight : children[0].implicitHeight + 2*root._topBottomMargins + + enum ViewType{ + SmallView, LargeView + } + property var type : AccountDelegate.SmallView RowLayout { - anchors.fill: parent - spacing: 12 + spacing: root._spacing + + anchors { + top: root.top + left: root.left + right: root.rigth + leftMargin : root._leftRightMargins + rightMargin : root._leftRightMargins + topMargin : root._topBottomMargins + bottomMargin : root._topBottomMargins + } Rectangle { id: avatar @@ -48,8 +97,19 @@ Item { colorScheme: root.colorScheme anchors.fill: parent text: root.user.avatarText.toUpperCase() - type: Label.LabelType.Body - color: root.colorScheme.text_invert + type: { + switch (root.type) { + case AccountDelegate.SmallView: return Label.Body + case AccountDelegate.LargeView: return Label.Title + } + } + font.weight: Font.Normal + color: { + switch(root.type) { + case AccountDelegate.SmallView: return root.colorScheme.text_norm + case AccountDelegate.LargeView: return root.colorScheme.text_invert + } + } horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter } @@ -63,16 +123,78 @@ Item { spacing: 0 Label { + Layout.maximumWidth: root.width - ( + root._spacing + avatar.width + 2*root._leftRightMargins + ) + colorScheme: root.colorScheme text: user.username - type: Label.LabelType.Body + type: { + switch (root.type) { + case AccountDelegate.SmallView: return Label.Body + case AccountDelegate.LargeView: return Label.Title + } + } + elide: Text.ElideMiddle } - Label { - colorScheme: root.colorScheme - text: user.captionText - type: Label.LabelType.Caption + Item { implicitHeight: root.type == AccountDelegate.LargeView ? 6 : 0 } + + RowLayout { + Label { + colorScheme: root.colorScheme + text: root.usedSpace + color: root.usedSpaceColor + type: { + switch (root.type) { + case AccountDelegate.SmallView: return Label.Caption + case AccountDelegate.LargeView: return Label.Body + } + } + } + + Label { + colorScheme: root.colorScheme + text: " / " + root.totalSpace + color: root.colorScheme.text_weak + type: { + switch (root.type) { + case AccountDelegate.SmallView: return Label.Caption + case AccountDelegate.LargeView: return Label.Body + } + } + } + } + + + Rectangle { + visible: root.type == AccountDelegate.LargeView + + width: 140 + height: 4 + radius: 3 + color: root.colorScheme.border_weak + + Rectangle { + radius: 3 + color: root.usedSpaceColor + anchors { + top : parent.top + bottom : parent.bottom + left : parent.left + } + width: Math.min(1,Math.max(0.02,root.usedFraction)) * parent.width + } } } + + Item { + Layout.fillWidth: true + } + } + + MouseArea { + anchors.fill: root + onClicked: root.clicked() } } diff --git a/internal/frontend/qml/AccountView.qml b/internal/frontend/qml/AccountView.qml index 66f87424..d1e11044 100644 --- a/internal/frontend/qml/AccountView.qml +++ b/internal/frontend/qml/AccountView.qml @@ -21,34 +21,245 @@ import QtQuick.Controls 2.12 import Proton 4.0 -Item { +ScrollView { id: root property ColorScheme colorScheme + property var backend + property var notifications + property var user - implicitHeight: children[0].implicitHeight - implicitWidth: children[0].implicitWidth + clip: true + contentWidth: pane.width + contentHeight: pane.height + + property int _leftRightMargins: 64 + property int _topBottomMargins: 68 + property int _spacing: 22 + + Rectangle { + anchors { + bottom: pane.bottom + } + color: root.colorScheme.background_weak + width: root.width + height: configuration.height + root._topBottomMargins + } + + signal showSignIn() + signal showSetupGuide(var user, string address) ColumnLayout { - anchors.fill: parent - spacing: 0 + id: pane - Rectangle { - Layout.fillWidth: true - Layout.minimumHeight: 277 - Layout.maximumHeight: 277 + width: root.width - color: root.colorScheme.background_norm + ColumnLayout { + spacing: root._spacing + Layout.topMargin: root._topBottomMargins + Layout.leftMargin: root._leftRightMargins + Layout.rightMargin: root._leftRightMargins + Layout.maximumWidth: root.width - 2*root._leftRightMargins - ColumnLayout { + RowLayout { // account delegate with action buttons + Layout.fillWidth: true + AccountDelegate { + Layout.fillWidth: true + colorScheme: root.colorScheme + user: root.user + type: AccountDelegate.LargeView + enabled: root.user.loggedIn + } + + Button { + Layout.alignment: Qt.AlignTop + colorScheme: root.colorScheme + text: qsTr("Sign out") + secondary: true + visible: root.user.loggedIn + onClicked: root.user.logout() + } + + Button { + Layout.alignment: Qt.AlignTop + colorScheme: root.colorScheme + icon.source: "icons/ic-trash.svg" + secondary: true + visible: root.user.loggedIn + onClicked: root.user.remove() + } + + Button { + Layout.alignment: Qt.AlignTop + colorScheme: root.colorScheme + text: qsTr("Sign in") + secondary: true + visible: !root.user.loggedIn + onClicked: root.parent.rightContent.showSignIn() + } } + + Rectangle { + Layout.fillWidth: true + height: 1 + color: root.colorScheme.border_weak + } + + SettingsItem { + colorScheme: root.colorScheme + text: qsTr("Email clients") + actionText: qsTr("Configure") + description: "MISSING WIREFRAME" // TODO + type: SettingsItem.Button + enabled: root.user.loggedIn + visible: !root.user.splitMode + onClicked: root.showSetupGuide(root.user,user.addresses[0]) + } + + SettingsItem { + id: splitMode + colorScheme: root.colorScheme + text: qsTr("Split addresses") + description: qsTr("Split addresses allows you to configure multiple email addresses individually. Changing its mode will require you to delete your accounts(s) from your email client and begin the setup process from scratch.") + type: SettingsItem.Toggle + checked: root.user.splitMode + visible: root.user.addresses.length > 1 + enabled: root.user.loggedIn + onClicked: { + if (!splitMode.checked){ + root.notifications.askEnableSplitMode(user) + } else { + root.user.toggleSplitMode(!splitMode.checked) + } + } + } + + RowLayout { + Layout.fillWidth: true + enabled: root.user.loggedIn + + visible: root.user.splitMode + + ComboBox { + id: addressSelector + Layout.fillWidth: true + model: root.user.addresses + + property var _topBottomMargins : 8 + property var _leftRightMargins : 16 + + background: RoundedRectangle { + radiusTopLeft : 6 + radiusTopRight : 6 + radiusBottomLeft : addressSelector.down ? 0 : 6 + radiusBottomRight : addressSelector.down ? 0 : 6 + + height: addressSelector.contentItem.height + //width: addressSelector.contentItem.width + + fillColor : root.colorScheme.background_norm + strokeColor : root.colorScheme.border_norm + strokeWidth : 1 + } + + delegate: Rectangle { + id: listItem + width: root.width + height: children[0].height + 4 + 2*addressSelector._topBottomMargins + + Label { + anchors { + top : parent.top + left : parent.left + topMargin : addressSelector._topBottomMargins + 4 + leftMargin : addressSelector._leftRightMargins + } + + colorScheme: root.colorScheme + text: modelData + elide: Text.ElideMiddle + } + + property bool isOver: false + color: { + if (listItem.isOver) return root.colorScheme.interaction_weak_hover + if (addressSelector.highlightedIndex === index) return root.colorScheme.interaction_weak + return root.colorScheme.background_norm + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: listItem.isOver = true + onExited: listItem.isOver = false + onClicked : { + addressSelector.currentIndex = index + addressSelector.popup.close() + } + } + } + + contentItem: Label { + topPadding : addressSelector._topBottomMargins+4 + bottomPadding : addressSelector._topBottomMargins + leftPadding : addressSelector._leftRightMargins + rightPadding : addressSelector._leftRightMargins + + colorScheme: root.colorScheme + text: addressSelector.displayText + elide: Text.ElideMiddle + } + } + + Button { + colorScheme: root.colorScheme + text: qsTr("Configure") + secondary: true + onClicked: root.showSetupGuide(root.user, addressSelector.displayText) + } + } + + Item {implicitHeight: 1} } - Rectangle { - Layout.fillWidth: true - Layout.fillHeight: true + ColumnLayout { + id: configuration + Layout.bottomMargin: root._topBottomMargins + Layout.leftMargin: root._leftRightMargins + Layout.rightMargin: root._leftRightMargins + Layout.maximumWidth: root.width - 2*root._leftRightMargins + spacing: root._spacing + visible: root.user.loggedIn - color: root.colorScheme.background_weak + property string currentAddress: addressSelector.displayText + + Item {height: 1} + + Label { + colorScheme: root.colorScheme + text: qsTr("Mailbox details") + type: Label.Body_semibold + } + + Configuration { + colorScheme: root.colorScheme + title: qsTr("IMAP") + hostname: root.backend.hostname + port: root.backend.portIMAP.toString() + username: configuration.currentAddress + password: root.user.password + security: "STARTTLS" + } + + Configuration { + colorScheme: root.colorScheme + title: qsTr("SMTP") + hostname : root.backend.hostname + port : root.backend.portSMTP.toString() + username : configuration.currentAddress + password : root.user.password + security : root.backend.useSSLforSMTP ? "SSL" : "STARTTLS" + } } } } diff --git a/internal/frontend/qml/Banner.qml b/internal/frontend/qml/Banner.qml index 4a6aaea8..7cb26c55 100644 --- a/internal/frontend/qml/Banner.qml +++ b/internal/frontend/qml/Banner.qml @@ -28,9 +28,13 @@ Popup { property ColorScheme colorScheme property Notification notification + property var mainWindow + + topMargin: 37 + leftMargin: (mainWindow.width - root.implicitWidth)/2 implicitHeight: contentLayout.implicitHeight + contentLayout.anchors.topMargin + contentLayout.anchors.bottomMargin - implicitWidth: contentLayout.implicitWidth + contentLayout.anchors.leftMargin + contentLayout.anchors.rightMargin + implicitWidth: 600 // contentLayout.implicitWidth + contentLayout.anchors.leftMargin + contentLayout.anchors.rightMargin popupType: ApplicationWindow.PopupType.Banner @@ -74,13 +78,13 @@ Popup { } switch (root.notification.type) { - case Notification.NotificationType.Info: + case Notification.NotificationType.Info: return root.colorScheme.signal_info - case Notification.NotificationType.Success: + case Notification.NotificationType.Success: return root.colorScheme.signal_success - case Notification.NotificationType.Warning: + case Notification.NotificationType.Warning: return root.colorScheme.signal_warning - case Notification.NotificationType.Danger: + case Notification.NotificationType.Danger: return root.colorScheme.signal_danger } } @@ -109,13 +113,13 @@ Popup { } switch (root.notification.type) { - case Notification.NotificationType.Info: + case Notification.NotificationType.Info: return "./icons/ic-info-circle-filled.svg" - case Notification.NotificationType.Success: + case Notification.NotificationType.Success: return "./icons/ic-info-circle-filled.svg" - case Notification.NotificationType.Warning: + case Notification.NotificationType.Warning: return "./icons/ic-exclamation-circle-filled.svg" - case Notification.NotificationType.Danger: + case Notification.NotificationType.Danger: return "./icons/ic-exclamation-circle-filled.svg" } } @@ -145,13 +149,13 @@ Popup { } switch (root.notification.type) { - case Notification.NotificationType.Info: + case Notification.NotificationType.Info: return root.colorScheme.signal_info_active - case Notification.NotificationType.Success: + case Notification.NotificationType.Success: return root.colorScheme.signal_success_active - case Notification.NotificationType.Warning: + case Notification.NotificationType.Warning: return root.colorScheme.signal_warning_active - case Notification.NotificationType.Danger: + case Notification.NotificationType.Danger: return root.colorScheme.signal_danger_active } } @@ -183,22 +187,22 @@ Popup { var active switch (root.notification.type) { - case Notification.NotificationType.Info: + case Notification.NotificationType.Info: norm = root.colorScheme.signal_info hover = root.colorScheme.signal_info_hover active = root.colorScheme.signal_info_active break; - case Notification.NotificationType.Success: + case Notification.NotificationType.Success: norm = root.colorScheme.signal_success hover = root.colorScheme.signal_success_hover active = root.colorScheme.signal_success_active break; - case Notification.NotificationType.Warning: + case Notification.NotificationType.Warning: norm = root.colorScheme.signal_warning hover = root.colorScheme.signal_warning_hover active = root.colorScheme.signal_warning_active break; - case Notification.NotificationType.Danger: + case Notification.NotificationType.Danger: norm = root.colorScheme.signal_danger hover = root.colorScheme.signal_danger_hover active = root.colorScheme.signal_danger_active diff --git a/internal/frontend/qml/Bridge.qml b/internal/frontend/qml/Bridge.qml index 7fba4a98..11c1151e 100644 --- a/internal/frontend/qml/Bridge.qml +++ b/internal/frontend/qml/Bridge.qml @@ -25,12 +25,7 @@ import Notifications 1.0 QtObject { id: root - property var backend - - signal login(string username, string password) - signal login2FA(string username, string code) - signal login2Password(string username, string password) - signal loginAbort(string username) + property var backend: go property Notifications _notifications: Notifications { id: notifications @@ -45,19 +40,23 @@ QtObject { visible: false backend: root.backend - notifications: notifications + notifications: root._notifications onLogin: { - root.login(username, password) + backend.login(username, password) } onLogin2FA: { - root.login2FA(username, code) + backend.login2FA(username, code) } onLogin2Password: { - root.login2Password(username, password) + backend.login2Password(username, password) } onLoginAbort: { - root.loginAbort(username) + backend.loginAbort(username) + } + + onVisibleChanged: { + backend.dockIconVisible = visible } } @@ -66,20 +65,45 @@ QtObject { visible: false backend: root.backend - notifications: notifications + notifications: root._notifications + + property var x_center: 10 + property var x_min: 0 + property var x_max: 100 + property var y_center: 1000 + property var y_min: 0 + property var y_max: 10000 + + x: bound(x_center,x_min, x_max-statusWindow.width) + y: bound(y_center,y_min, y_max-statusWindow.height) + onShowMainWindow: { mainWindow.visible = true } + onShowHelp: { - + mainWindow.showHelp() + mainWindow.visible = true } + onShowSettings: { - + mainWindow.showSettings() + mainWindow.visible = true } + + onShowSignIn: { + mainWindow.showSignIn(username) + mainWindow.visible = true + } + onQuit: { backend.quit() } + + function bound(num, lower_limit, upper_limit) { + return Math.max(lower_limit, Math.min(upper_limit, num)) + } } property SystemTrayIcon _trayIcon: SystemTrayIcon { @@ -88,103 +112,59 @@ QtObject { iconSource: "./icons/ic-systray.svg" onActivated: { function calcStatusWindowPosition(statusWidth, statusHeight) { - function bound(num, lower_limit, upper_limit) { - return Math.max(lower_limit, Math.min(upper_limit, num)) + function isInInterval(num, lower_limit, upper_limit) { + return lower_limit <= num && num <= upper_limit } - // checks if rect1 fits within rect2 - function isRectFit(rect1, rect2) { - //if (rect2.) - if ((rect2.left > rect1.left) || - (rect2.right < rect1.right) || - (rect2.top > rect1.top) || - (rect2.bottom < rect1.bottom)) { - return false - } - return true - } // First we get icon center position. // On some platforms (X11 / Wayland) Qt does not provide icon geometry info. // In this case we rely on cursor position + var iconWidth = geometry.width *1.2 + var iconHeight = geometry.height *1.2 var iconCenter = Qt.point(geometry.x + (geometry.width / 2), geometry.y + (geometry.height / 2)) - if (geometry.width == 0 && geometry.height == 0) { iconCenter = backend.getCursorPos() + // fallback: simple guess, no data to estimate + iconWidth = 25 + iconHeight = 25 } - // Now bound this position to virtual screen available rect - // TODO: here we should detect which screen mouse is on and use that screen available geometry to bound - iconCenter.x = bound(iconCenter.x, 0, Qt.application.screens[0].desktopAvailableWidth) - iconCenter.y = bound(iconCenter.y, 0, Qt.application.screens[0].desktopAvailableHeight) + // Find screen + var screen = Qt.application.screens[0] - var x = 0 - var y = 0 - - // Check if window may fit above - x = iconCenter.x - statusWidth / 2 - y = iconCenter.y - statusHeight - if (isRectFit( - Qt.rect(x, y, statusWidth, statusHeight), - // TODO: we should detect which screen mouse is on and use that screen available geometry to bound - Qt.rect(0, 0, Qt.application.screens[0].desktopAvailableWidth, Qt.application.screens[0].desktopAvailableHeight) - )) { - return Qt.point(x, y) + for (var i in Qt.application.screens) { + screen = Qt.application.screens[i] + if ( + isInInterval(iconCenter.x, screen.virtualX, screen.virtualX+screen.width) && + isInInterval(iconCenter.y, screen.virtualY, screen.virtualY+screen.heigh) + ) { + return + } } - // Check if window may fit below - x = iconCenter.x - statusWidth / 2 - y = iconCenter.y - if (isRectFit( - Qt.rect(x, y, statusWidth, statusHeight), - // TODO: we should detect which screen mouse is on and use that screen available geometry to bound - Qt.rect(0, 0, Qt.application.screens[0].desktopAvailableWidth, Qt.application.screens[0].desktopAvailableHeight) - )) { - return Qt.point(x, y) - } - - // Check if window may fit to the left - x = iconCenter.x - statusWidth - y = iconCenter.y - statusHeight / 2 - if (isRectFit( - Qt.rect(x, y, statusWidth, statusHeight), - // TODO: we should detect which screen mouse is on and use that screen available geometry to bound - Qt.rect(0, 0, Qt.application.screens[0].desktopAvailableWidth, Qt.application.screens[0].desktopAvailableHeight) - )) { - return Qt.point(x, y) - } - - // Check if window may fit to the right - x = iconCenter.x - y = iconCenter.y - statusHeight / 2 - if (isRectFit( - Qt.rect(x, y, statusWidth, statusHeight), - // TODO: we should detect which screen mouse is on and use that screen available geometry to bound - Qt.rect(0, 0, Qt.application.screens[0].desktopAvailableWidth, Qt.application.screens[0].desktopAvailableHeight) - )) { - return Qt.point(x, y) - } - - // TODO: add fallback + // Calculate allowed square where status window top left corner can be positioned + statusWindow.x_center = iconCenter.x + statusWindow.y_center = iconCenter.y + statusWindow.x_min = screen.virtualX + iconWidth + statusWindow.x_max = screen.virtualX + screen.width - iconWidth + statusWindow.y_min = screen.virtualY + iconHeight + statusWindow.y_max = screen.virtualY + screen.height - iconHeight } switch (reason) { - case SystemTrayIcon.Unknown: + case SystemTrayIcon.Unknown: break; - case SystemTrayIcon.Context: - case SystemTrayIcon.Trigger:!statusWindow.visible - if (!statusWindow.visible) { - var point = calcStatusWindowPosition(statusWindow.width, statusWindow.height) - statusWindow.x = point.x - statusWindow.y = point.y - } + case SystemTrayIcon.Context: + case SystemTrayIcon.Trigger: + calcStatusWindowPosition() statusWindow.visible = !statusWindow.visible break - case SystemTrayIcon.DoubleClick: - case SystemTrayIcon.MiddleClick: + case SystemTrayIcon.DoubleClick: + case SystemTrayIcon.MiddleClick: mainWindow.visible = !mainWindow.visible break; - default: + default: break; } } diff --git a/internal/frontend/qml/BridgeTest/UserControl.qml b/internal/frontend/qml/BridgeTest/UserControl.qml index 881f8695..911abc11 100644 --- a/internal/frontend/qml/BridgeTest/UserControl.qml +++ b/internal/frontend/qml/BridgeTest/UserControl.qml @@ -236,6 +236,53 @@ ColumnLayout { } } + Button { + colorScheme: root.colorScheme + text: "Login Finished" + + onClicked: { + root.backend.loginFinished() + user.resetLoginRequests() + } + } + + RowLayout { + TextField { + colorScheme: root.colorScheme + label: "used:" + text: user && user.usedBytes ? user.usedBytes : 0 + validator: DoubleValidator {bottom: 1; top: 1024*1024*1024*1024*1024} + onEditingFinished: { + user.usedBytes = parseFloat(text) + } + implicitWidth: 200 + } + TextField { + colorScheme: root.colorScheme + label: "total:" + text: user && user.totalBytes ? user.totalBytes : 0 + validator: DoubleValidator {bottom: 1; top: 1024*1024*1024*1024*1024} + onEditingFinished: { + user.totalBytes = parseFloat(text) + } + implicitWidth: 200 + } + } + + RowLayout { + Label {colorScheme: root.colorScheme; text: "Split mode"} + Toggle { colorScheme: root.colorScheme; checked: user ? user.splitMode : false; onClicked: {user.splitMode = !user.splitMode}} + Button { colorScheme: root.colorScheme; text: "Toggle Finished"; onClicked: {user.toggleSplitModeFinished()}} + } + + TextArea { + colorScheme: root.colorScheme + text: user && user.addresses ? user.addresses.join("\n") : "user@protonmail.com" + Layout.fillWidth: true + onEditingFinished: { + user.addresses = text.split("\n") + } + } Item { Layout.fillHeight: true diff --git a/internal/frontend/qml/Bridge_test.qml b/internal/frontend/qml/Bridge_test.qml index d81e0b1a..03a8f1bd 100644 --- a/internal/frontend/qml/Bridge_test.qml +++ b/internal/frontend/qml/Bridge_test.qml @@ -33,8 +33,10 @@ import Notifications 1.0 Window { id: root - width: 640 - height: 480 + x: 10 + y: 10 + width: 800 + height: 600 property ColorScheme colorScheme: ProtonStyle.darkStyle @@ -103,12 +105,21 @@ Window { QtObject { property string username: "" property bool loggedIn: false + property bool splitMode: false property bool setupGuideSeen: true - property string captionText: "50.3 MB / 20 GB" + property var usedBytes: 5350*1024*1024 + property var totalBytes: 20*1024*1024*1024 property string avatarText: "jd" + property string password: "SMj975NnEYYsqu55GGmlpv" + property var addresses: [ + "janedoe@protonmail.com", + "jane@pm.me", + "jdoe@pm.me" + ] + signal loginUsernamePasswordError() signal loginFreeUserError() signal loginConnectionError() @@ -130,6 +141,30 @@ Window { root.log("<- User (" + username + "): " + msg) } + function toggleSplitMode(makeActive) { + userSignal("toggle split mode "+makeActive) + } + signal toggleSplitModeFinished() + + function configureAppleMail(address){ + userSignal("confugure apple mail "+address) + } + + function logout(){ + userSignal("logout") + loggedIn = false + } + function remove(){ + console.log("remove this", users.count) + for (var i=0; i disk cache", enableDiskCache, diskCachePath) + } + signal changeLocalCacheFinished() + + + // Settings + property bool isAutomaticUpdateOn : true + function toggleAutomaticUpdate(makeItActive) { + console.debug("-> silent updates", makeItActive, root.isAutomaticUpdateOn) + root.isAutomaticUpdateOn = makeItActive + } + + property bool isAutostartOn : true // Example of settings with loading state + function toggleAutostart(makeItActive) { + console.debug("-> autostart", makeItActive, root.isAutomaticUpdateOn) + } + signal toggleAutostartFinished() + + property bool isBetaEnabled : false + function toggleBeta(makeItActive){ + console.debug("-> beta", makeItActive, root.isBetaEnabled) + root.isBetaEnabled = makeItActive + } + + property bool isDoHEnabled : true + function toggleDoH(makeItActive){ + console.debug("-> DoH", makeItActive, root.isDoHEnabled) + root.isDoHEnabled = makeItActive + } + + property bool useSSLforSMTP: false + function toggleUseSSLforSMTP(makeItActive){ + console.debug("-> SMTP SSL", makeItActive, root.useSSLforSMTP) + } + signal toggleUseSSLFinished() + + property string hostname: "127.0.0.1" + property int portIMAP: 1143 + property int portSMTP: 1025 + function changePorts(imapPort, smtpPort){ + console.debug("-> ports", imapPort, smtpPort) + } + function isPortFree(port){ + if (port == portIMAP) return false + if (port == portSMTP) return false + if (port == 12345) return false + return true + } + signal changePortFinished() + signal portIssueIMAP() + signal portIssueSMTP() + + function triggerReset() { + console.debug("-> trigger reset") + } + signal resetFinished() + + property string logsPath: "/home/cuto" // StandardPaths.locate(StandardPaths.DesktopLocation) + property string version: "v2.0.X" + property string licensePath: "/home/cuto" // StandardPaths.locate(StandardPaths.DesktopLocation) + property string releaseNotesLink: "https://protonmail.com/download/bridge/early_releases.html" + + property string currentEmailClient: "" // "Apple Mail 14.0" + function updateCurrentMailClient(){ + currentEmailClient = "Apple Mail 14.0" + } + + function reportBug(description,address,emailClient,includeLogs){ + console.log("report bug") + console.log(" description",description) + console.log(" address",address) + console.log(" emailClient",emailClient) + console.log(" includeLogs",includeLogs) + } + signal reportBugFinished() signal bugReportSendSuccess() signal bugReportSendError() - signal cacheAnavailable() - signal cacheCantMove() + property var availableKeychain: ["gnome-keyring", "pass"] + property string selectedKeychain + function selectKeychain(wantedKeychain){ + selectedKeychain = wantedKeychain + } + signal hasNoKeychain() + + signal noActiveKeyForRecipient(string email) + signal showMainWindow() + + signal addressChanged(string address) + signal addressChangedLogout(string address) + signal userDisconnected(string username) + signal apiCertIssue() + + + + function login(username, password) { + root.log("-> login(" + username + ", " + password + ")") + + loginUser.username = username + loginUser.isLoginRequested = true + } + + function login2FA(username, code) { + root.log("-> login2FA(" + username + ", " + code + ")") + + loginUser.isLogin2FAProvided = true + } + + function login2Password(username, password) { + root.log("-> login2FA(" + username + ", " + password + ")") + + loginUser.isLogin2PasswordProvided = true + } + + function loginAbort(username) { + root.log("-> loginAbort(" + username + ")") + + loginUser.resetLoginRequests() + } - signal diskFull() onLoginUsernamePasswordError: { console.debug("<- loginUsernamePasswordError") @@ -557,6 +812,9 @@ Window { onLogin2PasswordErrorAbort: { console.debug("<- login2PasswordErrorAbort") } + onLoginFinished: { + console.debug("<- loginFinished") + } onInternetOff: { console.debug("<- internetOff") @@ -571,30 +829,6 @@ Window { Bridge { backend: root - onLogin: { - root.log("-> login(" + username + ", " + password + ")") - - loginUser.username = username - loginUser.isLoginRequested = true - } - - onLogin2FA: { - root.log("-> login2FA(" + username + ", " + code + ")") - - loginUser.isLogin2FAProvided = true - } - - onLogin2Password: { - root.log("-> login2FA(" + username + ", " + password + ")") - - loginUser.isLogin2PasswordProvided = true - } - - onLoginAbort: { - root.log("-> loginAbort(" + username + ")") - - loginUser.resetLoginRequests() - } } } diff --git a/internal/frontend/qml/BugReportView.qml b/internal/frontend/qml/BugReportView.qml new file mode 100644 index 00000000..30868de0 --- /dev/null +++ b/internal/frontend/qml/BugReportView.qml @@ -0,0 +1,167 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.12 + +import Proton 4.0 + +SettingsView { + id: root + + property var selectedAddress + + Label { + text: qsTr("Report a problem") + colorScheme: root.colorScheme + type: Label.Heading + } + + + TextArea { + id: description + property int _minChars: 150 + property bool _inputOK: description.text.length>=description._minChars + + label: qsTr("Description") + colorScheme: root.colorScheme + Layout.fillWidth: true + Layout.minimumHeight: 100 + hint: description.text.length + "/800" + placeholderText: qsTr("Tell us what went wrong or isn't working (min. 150 characters).") + onEditingFinished: { + if (!description._inputOK) { + description.error = true + description.assistiveText = qsTr("Enter a problem description (min. 150 characters)") + } else { + description.error = false + description.assistiveText = "" + } + } + } + + + TextField { + id: address + property bool _inputOK: root.isValidEmail(address.text) + + label: qsTr("Your contact email") + colorScheme: root.colorScheme + Layout.fillWidth: true + placeholderText: qsTr("e.g. jane.doe@protonmail.com") + + onEditingFinished: { + if (!address._inputOK) { + address.error = true + address.assistiveText = qsTr("Enter valid email address") + } else { + address.assistiveText = "" + address.error = false + } + } + } + + TextField { + id: emailClient + property bool _inputOK: emailClient.text.length > 0 + + label: qsTr("Your email client (including version)") + colorScheme: root.colorScheme + Layout.fillWidth: true + placeholderText: qsTr("e.g. Apple Mail 14.0") + onEditingFinished: { + if (!emailClient._inputOK) { + emailClient.assistiveText = qsTr("Enter an email client name and version") + emailClient.error = true + } else { + emailClient.assistiveText = "" + emailClient.error = false + } + } + } + + + RowLayout { + CheckBox { + id: includeLogs + text: qsTr("Include my recent logs") + colorScheme: root.colorScheme + checked: true + } + Button { + Layout.leftMargin: 12 + text: qsTr("View logs") + secondary: true + colorScheme: root.colorScheme + onClicked: Qt.openUrlExternally("file://"+root.backend.logsPath) + } + } + + Label { + text: { + var address = "bridge@protonmail.com" + var mailTo = `${address}` + return qsTr("These reports are not end-to-end encrypted. In case of sensitive information, contact us at %1.").arg(mailTo) + } + colorScheme: root.colorScheme + Layout.fillWidth: true + wrapMode: Text.WordWrap + type: Label.Caption + color: root.colorScheme.text_weak + } + + Button { + id: sendButton + text: qsTr("Send") + colorScheme: root.colorScheme + onClicked: root.submit() + enabled: description._inputOK && address._inputOK && emailClient._inputOK + + Connections {target: root.backend; onReportBugFinished: sendButton.loading = false } + } + + function setDefaultValue() { + description.text = "" + address.text = root.selectedAddress + emailClient.text = root.backend.currentEmailClient + includeLogs.checked = true + } + + function isValidEmail(text){ + var reEmail = /\w+@\w+\.\w+/ + return reEmail.test(text) + } + + function submit() { + sendButton.loading = true + root.backend.reportBug( + description.text, + address.text, + emailClient.text, + includeLogs.checked + ) + } + + Component.onCompleted: root.setDefaultValue() + + + onBack: { + root.setDefaultValue() + root.parent.showHelpView() + } +} diff --git a/internal/frontend/qml/Configuration.qml b/internal/frontend/qml/Configuration.qml new file mode 100644 index 00000000..42521ed2 --- /dev/null +++ b/internal/frontend/qml/Configuration.qml @@ -0,0 +1,73 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.12 +import QtQuick.Controls.impl 2.12 + +import Proton 4.0 + +Rectangle { + id: root + + property ColorScheme colorScheme + property string title + property string hostname + property string port + property string username + property string password + property string security + + implicitWidth: 304 + implicitHeight: content.height + 2*root._margin + + color: root.colorScheme.background_norm + radius: 9 + + property int _margin: 24 + + ColumnLayout { + id: content + width: root.width - 2*root._margin + anchors{ + top: root.top + left: root.left + leftMargin : root._margin + rightMargin : root._margin + topMargin : root._margin + bottomMargin : root._margin + } + + spacing: 12 + + Label { + colorScheme: root.colorScheme + text: root.title + type: Label.Body_semibold + } + + Item{} + + ConfigurationItem{ colorScheme: root.colorScheme; label: qsTr("Hostname") ; value: root.hostname } + ConfigurationItem{ colorScheme: root.colorScheme; label: qsTr("Port") ; value: root.port } + ConfigurationItem{ colorScheme: root.colorScheme; label: qsTr("Username") ; value: root.username } + ConfigurationItem{ colorScheme: root.colorScheme; label: qsTr("Password") ; value: root.password } + ConfigurationItem{ colorScheme: root.colorScheme; label: qsTr("Security") ; value: root.security } + } +} + diff --git a/internal/frontend/qml/ConfigurationItem.qml b/internal/frontend/qml/ConfigurationItem.qml new file mode 100644 index 00000000..ed37b4ab --- /dev/null +++ b/internal/frontend/qml/ConfigurationItem.qml @@ -0,0 +1,81 @@ +// 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.Layouts 1.12 +import QtQuick.Controls.impl 2.12 + +import Proton 4.0 + +ColumnLayout { + id: root + Layout.fillWidth: true + + property var colorScheme + property string label + property string value + + RowLayout { + Layout.fillWidth: true + + ColumnLayout { + Label { + colorScheme: root.colorScheme + text: root.label + type: Label.Body + } + TextEdit { + id: valueText + text: root.value + color: root.colorScheme.text_weak + readOnly: true + selectByMouse: true + selectByKeyboard: true + selectionColor: root.colorScheme.text_weak + } + } + + Item { + Layout.fillWidth: true + } + + ColorImage { + source: "icons/ic-copy.svg" + color: root.colorScheme.text_norm + height: root.colorScheme.body_font_size + + MouseArea { + anchors.fill: parent + onClicked : { + valueText.select(0, valueText.length) + valueText.copy() + valueText.deselect() + } + onPressed: parent.scale = 0.90 + onReleased: parent.scale = 1 + } + + } + } + + + Rectangle { + Layout.fillWidth: true + height: 1 + color: root.colorScheme.border_norm + } +} diff --git a/internal/frontend/qml/ContentWrapper.qml b/internal/frontend/qml/ContentWrapper.qml index 98db99d0..07287042 100644 --- a/internal/frontend/qml/ContentWrapper.qml +++ b/internal/frontend/qml/ContentWrapper.qml @@ -26,12 +26,26 @@ Item { property ColorScheme colorScheme property var backend + property var notifications signal login(string username, string password) signal login2FA(string username, string code) signal login2Password(string username, string password) signal loginAbort(string username) + signal showSetupGuide(var user, string address) + + property var noUser: QtObject { + property var avatarText: "" + property var username: "" + property var password: "" + property var usedBytes: 1 + property var totalBytes: 1 + property var loggedIn: false + property var splitMode: false + property var addresses: [] + } + RowLayout { anchors.fill: parent spacing: 0 @@ -91,6 +105,8 @@ Item { horizontalPadding: 0 icon.source: "./icons/ic-question-circle.svg" + + onClicked: rightContent.showHelpView() } Button { @@ -109,10 +125,14 @@ Item { horizontalPadding: 0 icon.source: "./icons/ic-cog-wheel.svg" + + onClicked: rightContent.showGeneralSettings() } } - // Separator + Item {implicitHeight:10} + + // Separator line Rectangle { Layout.fillWidth: true Layout.minimumHeight: 1 @@ -122,14 +142,20 @@ Item { ListView { id: accounts + + property var _topBottomMargins: 24 + property var _leftRightMargins: 16 + Layout.fillWidth: true Layout.fillHeight: true - Layout.leftMargin: 16 - Layout.rightMargin: 16 - Layout.topMargin: 24 - Layout.bottomMargin: 24 + Layout.leftMargin: accounts._leftRightMargins + Layout.rightMargin: accounts._leftRightMargins + Layout.topMargin: accounts._topBottomMargins + Layout.bottomMargin: accounts._topBottomMargins spacing: 12 + clip: true + boundsBehavior: Flickable.StopAtBounds header: Rectangle { height: headerLabel.height+16 @@ -142,11 +168,28 @@ Item { } } + highlight: Rectangle { + color: leftBar.colorScheme.interaction_default_active + radius: 4 + } + model: root.backend.users delegate: AccountDelegate{ + width: leftBar.width - 2*accounts._leftRightMargins + id: accountDelegate colorScheme: leftBar.colorScheme - user: modelData + user: root.backend.users.get(index) + onClicked: { + var user = root.backend.users.get(index) + accounts.currentIndex = index + if (user.loggedIn) { + rightContent.showAccount() + } else { + signIn.username = user.username + rightContent.showSignIn() + } + } } } @@ -181,15 +224,16 @@ Item { icon.source: "./icons/ic-plus.svg" - onClicked: root.showSignIn() + onClicked: { + signIn.username = "" + rightContent.showSignIn() + } } } } } - Rectangle { - id: rightPlane - + Rectangle { // right content background Layout.fillWidth: true Layout.fillHeight: true @@ -199,14 +243,44 @@ Item { id: rightContent anchors.fill: parent - AccountView { + AccountView { // 0 colorScheme: root.colorScheme + backend: root.backend + notifications: root.notifications + user: { + if (accounts.currentIndex < 0) return root.noUser + if (root.backend.users.count == 0) return root.noUser + return root.backend.users.get(accounts.currentIndex) + } + onShowSignIn: { + signIn.username = this.user.username + rightContent.showSignIn() + } + onShowSetupGuide: { + root.showSetupGuide(user,address) + } } - GridLayout { + GridLayout { // 1 + columns: 2 + + Button { + id: backButton + Layout.leftMargin: 18 + Layout.topMargin: 10 + Layout.alignment: Qt.AlignTop + + colorScheme: root.colorScheme + onClicked: rightContent.showAccount() + icon.source: "icons/ic-arrow-left.svg" + secondary: true + horizontalPadding: 8 + } + SignIn { + id: signIn Layout.topMargin: 68 - Layout.leftMargin: 80 + Layout.leftMargin: 80 - backButton.width - 18 Layout.rightMargin: 80 Layout.bottomMargin: 68 Layout.preferredWidth: 320 @@ -214,21 +288,70 @@ Item { Layout.fillHeight: true colorScheme: root.colorScheme - user: (root.backend.users.count === 1 && root.backend.users.get(0).loggedIn === false) ? root.backend.users.get(0) : undefined backend: root.backend - onLogin : { root.login ( username , password ) } - onLogin2FA : { root.login2FA ( username , code ) } - onLogin2Password : { root.login2Password ( username , password ) } - onLoginAbort : { root.loginAbort ( username ) } + onLogin : { root.backend.login ( username , password ) } + onLogin2FA : { root.backend.login2FA ( username , code ) } + onLogin2Password : { root.backend.login2Password ( username , password ) } + onLoginAbort : { root.backend.loginAbort ( username ) } } } + + GeneralSettings { // 2 + colorScheme: root.colorScheme + backend: root.backend + notifications: root.notifications + } + + PortSettings { // 3 + colorScheme: root.colorScheme + backend: root.backend + } + + SMTPSettings { // 4 + colorScheme: root.colorScheme + backend: root.backend + } + + LocalCacheSettings { // 5 + colorScheme: root.colorScheme + backend: root.backend + notifications: root.notifications + } + + HelpView { // 6 + colorScheme: root.colorScheme + backend: root.backend + } + + BugReportView { // 7 + colorScheme: root.colorScheme + backend: root.backend + selectedAddress: { + if (accounts.currentIndex < 0) return "" + if (root.backend.users.count == 0) return "" + return root.backend.users.get(accounts.currentIndex).addresses[0] + } + } + + function showAccount () { rightContent.currentIndex = 0 } + function showSignIn () { rightContent.currentIndex = 1 } + function showGeneralSettings () { rightContent.currentIndex = 2 } + function showPortSettings () { rightContent.currentIndex = 3 } + function showSMTPSettings () { rightContent.currentIndex = 4 } + function showLocalCacheSettings () { rightContent.currentIndex = 5 } + function showHelpView () { rightContent.currentIndex = 6 } + function showBugReport () { rightContent.currentIndex = 7 } } } } - - function showSignIn() { - rightContent.currentIndex = 1 + function showLocalCacheSettings(){rightContent.showLocalCacheSettings() } + function showSettings(){rightContent.showGeneralSettings() } + function showHelp(){rightContent.showHelpView() } + function showSignIn(username){ + signIn.username = username + rightContent.showSignIn() } + } diff --git a/internal/frontend/qml/GeneralSettings.qml b/internal/frontend/qml/GeneralSettings.qml new file mode 100644 index 00000000..ccedbd15 --- /dev/null +++ b/internal/frontend/qml/GeneralSettings.qml @@ -0,0 +1,168 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.13 +import QtQuick.Controls.impl 2.13 + +import Proton 4.0 + +SettingsView { + id: root + + property bool _isAdvancedShown: false + property var notifications + + Label { + colorScheme: root.colorScheme + text: qsTr("Settings") + type: Label.Heading + Layout.fillWidth: true + } + + SettingsItem { + id: autoUpdate + colorScheme: root.colorScheme + text: qsTr("Automatic updates") + description: qsTr("Bridge will automatically update in the background.") + type: SettingsItem.Toggle + checked: root.backend.isAutomaticUpdateOn + onClicked: root.backend.toggleAutomaticUpdate(!autoUpdate.checked) + } + + SettingsItem { + id: autostart + colorScheme: root.colorScheme + text: qsTr("Automatically start Bridge") + description: qsTr("The app will autostart everytime you reset your device.") + type: SettingsItem.Toggle + checked: root.backend.isAutostartOn + onClicked: { + autostart.loading = true + root.backend.toggleAutostart(!autoUpdate.checked) + } + Connections{ + target: root.backend + onToggleAutostartFinished: { + autostart.loading = false + } + } + } + + SettingsItem { + id: beta + colorScheme: root.colorScheme + text: qsTr("Enable Beta access") + description: qsTr("Be the first one to see new features.") + type: SettingsItem.Toggle + checked: root.backend.isBetaEnabled + onClicked: { + if (!beta.checked) { + root.notifications.askEnableBeta() + } else { + root.notifications.askDisableBeta() + } + } + } + + RowLayout { + ColorImage { + Layout.alignment: Qt.AlignTop + + source: root._isAdvancedShown ? "icons/ic-chevron-up.svg" : "icons/ic-chevron-down.svg" + color: root.colorScheme.interaction_norm + height: root.colorScheme.body_font_size + MouseArea { + anchors.fill: parent + onClicked: root._isAdvancedShown = !root._isAdvancedShown + } + } + + Label { + id: advSettLabel + colorScheme: root.colorScheme + text: qsTr("Advanced settings") + color: root.colorScheme.interaction_norm + type: Label.Body + + MouseArea { + anchors.fill: parent + onClicked: root._isAdvancedShown = !root._isAdvancedShown + } + } + } + + SettingsItem { + id: doh + visible: root._isAdvancedShown + colorScheme: root.colorScheme + text: qsTr("Alternative routing") + description: qsTr("If Proton’s servers are blocked in your location, alternative network routing will be used to reach Proton.") + type: SettingsItem.Toggle + checked: root.backend.isDoHEnabled + onClicked: root.backend.toggleDoH(!doh.checked) + } + + SettingsItem { + id: ports + visible: root._isAdvancedShown + colorScheme: root.colorScheme + text: qsTr("Default ports") + actionText: qsTr("Change") + description: qsTr("Choose which ports are used by default.") + type: SettingsItem.Button + onClicked: root.parent.showPortSettings() + } + + SettingsItem { + id: smtp + visible: root._isAdvancedShown + colorScheme: root.colorScheme + text: qsTr("SMTP connection mode") + actionText: qsTr("Change") + description: qsTr("Change the protocol Bridge and your client use to connect.") + type: SettingsItem.Button + onClicked: root.parent.showSMTPSettings() + } + + SettingsItem { + id: cache + visible: root._isAdvancedShown + colorScheme: root.colorScheme + text: qsTr("Local cache") + actionText: qsTr("Configure") + description: qsTr("Configure Bridge's local cache settings.") + type: SettingsItem.Button + onClicked: root.parent.showLocalCacheSettings() + } + + SettingsItem { + id: reset + visible: root._isAdvancedShown + colorScheme: root.colorScheme + text: qsTr("Reset Bridge") + actionText: qsTr("Reset") + description: qsTr("Remove all accounts, clear cached data, and restore the original settings.") + type: SettingsItem.Button + onClicked: { + root.notifications.askResetBridge() + } + } + + onBack: root.parent.showAccount() +} diff --git a/internal/frontend/qml/HelpView.qml b/internal/frontend/qml/HelpView.qml new file mode 100644 index 00000000..a14f1cb9 --- /dev/null +++ b/internal/frontend/qml/HelpView.qml @@ -0,0 +1,110 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.12 + +import Proton 4.0 + +SettingsView { + id: root + + Label { + colorScheme: root.colorScheme + text: qsTr("Help") + type: Label.Heading + Layout.fillWidth: true + } + + SettingsItem { + id: setupPage + colorScheme: root.colorScheme + text: qsTr("Installation and setup") + actionText: qsTr("Go to help topics") + actionIcon: "./icons/ic-external-link.svg" + description: qsTr("Get help setting up your client with our instructions and FAQs.") + type: SettingsItem.PrimaryButton + onClicked: {Qt.openUrlExternally("https://protonmail.com/bridge/install")} + } + + SettingsItem { + id: checkUpdates + colorScheme: root.colorScheme + text: qsTr("Updates") + actionText: qsTr("Check now") + description: qsTr("Check that you're using the latest version of Bridge. To stay up to date, enable auto-updates in settings.") + type: SettingsItem.Button + onClicked: { + checkUpdates.loading = true + root.backend.checkUpdates() + } + + Connections {target: root.backend; onCheckUpdatesFinished: checkUpdates.loading = false} + } + + SettingsItem { + id: logs + colorScheme: root.colorScheme + text: qsTr("Logs") + actionText: qsTr("View logs") + description: qsTr("Open and review logs to troubleshoot.") + type: SettingsItem.Button + onClicked: {Qt.openUrlExternally(root.backend.logsPath)} + } + + SettingsItem { + id: reportBug + colorScheme: root.colorScheme + text: qsTr("Report a problem") + actionText: qsTr("Report a problem") + description: qsTr("Something not working as expected? Let us know.") + type: SettingsItem.Button + onClicked: { + root.backend.updateCurrentMailClient() + root.parent.showBugReport() + } + } + + Label { + Layout.alignment: Qt.AlignHCenter + colorScheme: root.colorScheme + type: Label.Caption + color: root.colorScheme.text_weak + textFormat: Text.RichText + linkColor: root.colorScheme.interaction_norm_active + + text: { + var version = root.backend.version + var license = qsTr("License") + var licensePath = root.backend.licensePath + var release= qsTr("Release notes") + var releaseNotesLink = root.backend.releaseNotesLink + return `

Proton Mail Bridge v${version}
+ © 2021 Proton Technologies AG
+ ${license} + ${release} +

` + } + + onLinkActivated: Qt.openUrlExternally(link) + } + + onBack: { + root.parent.showAccount() + } +} diff --git a/internal/frontend/qml/LocalCacheSettings.qml b/internal/frontend/qml/LocalCacheSettings.qml new file mode 100644 index 00000000..8809ff47 --- /dev/null +++ b/internal/frontend/qml/LocalCacheSettings.qml @@ -0,0 +1,146 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.13 +import QtQuick.Controls.impl 2.13 +import QtQuick.Dialogs 1.1 + +import Proton 4.0 + +SettingsView { + id: root + + property var notifications + property bool _diskCacheEnabled: true + property string _diskCachePath: "/home" + + Label { + colorScheme: root.colorScheme + text: qsTr("Local cache") + type: Label.Heading + Layout.fillWidth: true + } + + Label { + colorScheme: root.colorScheme + text: qsTr("Bridge caches your encrypted messages localy to optimise the communication with the local client. Disabling this feature might have a nevative impact on performance.") + type: Label.Body + color: root.colorScheme.text_weak + Layout.fillWidth: true + Layout.maximumWidth: this.parent.Layout.maximumWidth + wrapMode: Text.WordWrap + } + + SettingsItem { + colorScheme: root.colorScheme + text: qsTr("Enable local cache") + description: "When enabled messages are stored on disk." // TODO: wrong text in wireframe + type: SettingsItem.Toggle + checked: root._diskCacheEnabled + onClicked: root._diskCacheEnabled = !root._diskCacheEnabled + } + + SettingsItem { + colorScheme: root.colorScheme + text: qsTr("Current cache location") + actionText: qsTr("Change location") + description: root._diskCachePath + type: SettingsItem.Button + enabled: root._diskCacheEnabled + onClicked: { + pathDialog.open() + } + + FileDialog { + id: pathDialog + title: qsTr("Select cache location") + folder: shortcuts.home + onAccepted: root.sanitizePath(pathDialog.fileUrl.toString()) + selectFolder: true + } + } + + RowLayout { + spacing: 12 + + Button { + id: submitButton + colorScheme: root.colorScheme + text: qsTr("Save and restart") + enabled: ( + root.backend.diskCachePath != root._diskCachePath || + root.backend.isDiskCacheEnabled != root._diskCacheEnabled + ) + onClicked: { + root.submit() + } + } + + Button { + colorScheme: root.colorScheme + text: qsTr("Cancel") + onClicked: root.back() + secondary: true + } + + Connections { + target: root.backend + + onChangeLocalCacheFinished: { + submitButton.loading = false + root.setDefaultValues() + } + } + } + + onBack: { + root.parent.showGeneralSettings() + root.setDefaultValues() + } + + function submit(){ + console.log("submit") + if (!root._diskCacheEnabled && root.backend.isDiskCacheEnabled) { + root.notifications.askDisableLocalCache() + return + } + + if (root._diskCacheEnabled && !root.backend.isDiskCacheEnabled) { + root.notifications.askEnableLocalCache(root._diskCachePath) + return + } + + // Not asking, only changing path + submitButton.loading = true + root.backend.changeLocalCache(root.backend.isDiskCacheEnabled, root._diskCachePath) + } + + function setDefaultValues(){ + root._diskCacheEnabled = root.backend.isDiskCacheEnabled + root._diskCachePath = root.backend.diskCachePath + } + + function sanitizePath(path) { + var pattern = "file://" + if (root.backend.goos=="windows") pattern+="/" + root._diskCachePath = path.replace(pattern, "") + } + + Component.onCompleted: root.setDefaultValues() +} diff --git a/internal/frontend/qml/MainWindow.qml b/internal/frontend/qml/MainWindow.qml index bcf7cf38..d57a5843 100644 --- a/internal/frontend/qml/MainWindow.qml +++ b/internal/frontend/qml/MainWindow.qml @@ -62,7 +62,7 @@ ApplicationWindow { return } - root.showSetup(user) + root.showSetup(user,user.addresses[0]) } onRowsAboutToBeRemoved: { @@ -78,15 +78,6 @@ ApplicationWindow { } } - function showSetup(user) { - setupGuide.user = user - if (setupGuide.user) { - contentLayout._showSetup = true - } else { - contentLayout._showSetup = false - } - } - StackLayout { id: contentLayout @@ -111,12 +102,18 @@ ApplicationWindow { } ContentWrapper { + id: contentWrapper colorScheme: root.colorScheme backend: root.backend + notifications: root.notifications Layout.fillHeight: true Layout.fillWidth: true + onShowSetupGuide: { + root.showSetup(user,address) + } + onLogin: { root.login(username, password) } @@ -161,7 +158,7 @@ ApplicationWindow { Layout.fillWidth: true onDismissed: { - root.showSetup(null) + root.showSetup(null,"") } } } @@ -169,5 +166,25 @@ ApplicationWindow { NotificationPopups { colorScheme: root.colorScheme notifications: root.notifications + mainWindow: root + } + + function showLocalCacheSettings() { contentWrapper.showLocalCacheSettings() } + function showSettings() { contentWrapper.showSettings() } + function showHelp() { contentWrapper.showHelp() } + + function showSignIn(username) { + if (contentLayout.currentIndex == 1) return + contentWrapper.showSignIn(username) + } + + function showSetup(user, address) { + setupGuide.user = user + setupGuide.address = address + if (setupGuide.user) { + contentLayout._showSetup = true + } else { + contentLayout._showSetup = false + } } } diff --git a/internal/frontend/qml/NotificationDialog.qml b/internal/frontend/qml/NotificationDialog.qml index 914ba8f4..79e98962 100644 --- a/internal/frontend/qml/NotificationDialog.qml +++ b/internal/frontend/qml/NotificationDialog.qml @@ -55,13 +55,12 @@ Dialog { } switch (root.notification.type) { - case Notification.NotificationType.Info: - // TODO: Add info icon? - return "" - case Notification.NotificationType.Success: + case Notification.NotificationType.Info: + return "./icons/ic-info.svg" + case Notification.NotificationType.Success: return "./icons/ic-success.svg" - case Notification.NotificationType.Warning: - case Notification.NotificationType.Danger: + case Notification.NotificationType.Warning: + case Notification.NotificationType.Danger: return "./icons/ic-alert.svg" } } @@ -110,6 +109,8 @@ Dialog { action: modelData secondary: index > 0 + + loading: notification.loading } } } diff --git a/internal/frontend/qml/NotificationPopups.qml b/internal/frontend/qml/NotificationPopups.qml index bb9d6433..a98a4095 100644 --- a/internal/frontend/qml/NotificationPopups.qml +++ b/internal/frontend/qml/NotificationPopups.qml @@ -28,6 +28,7 @@ Item { property ColorScheme colorScheme property var notifications + property var mainWindow property int notificationWhitelist: NotificationFilter.FilterConsts.All property int notificationBlacklist: NotificationFilter.FilterConsts.None @@ -42,6 +43,7 @@ Item { Banner { colorScheme: root.colorScheme notification: bannerNotificationFilter.topmost + mainWindow: root.mainWindow } NotificationDialog { @@ -66,17 +68,17 @@ Item { NotificationDialog { colorScheme: root.colorScheme - notification: root.notifications.bugReportSendSuccess + notification: root.notifications.disableBeta } NotificationDialog { colorScheme: root.colorScheme - notification: root.notifications.bugReportSendError + notification: root.notifications.enableBeta } NotificationDialog { colorScheme: root.colorScheme - notification: root.notifications.cacheAnavailable + notification: root.notifications.cacheUnavailable } NotificationDialog { @@ -88,4 +90,24 @@ Item { colorScheme: root.colorScheme notification: root.notifications.diskFull } + + NotificationDialog { + colorScheme: root.colorScheme + notification: root.notifications.enableSplitMode + } + + NotificationDialog { + colorScheme: root.colorScheme + notification: root.notifications.disableLocalCache + } + + NotificationDialog { + colorScheme: root.colorScheme + notification: root.notifications.enableLocalCache + } + + NotificationDialog { + colorScheme: root.colorScheme + notification: root.notifications.resetBridge + } } diff --git a/internal/frontend/qml/Notifications/Notification.qml b/internal/frontend/qml/Notifications/Notification.qml index 5c267b53..3c773021 100644 --- a/internal/frontend/qml/Notifications/Notification.qml +++ b/internal/frontend/qml/Notifications/Notification.qml @@ -39,6 +39,7 @@ QtObject { property bool dismissed: false property bool active: false + property bool loading: false readonly property var occurred: active ? new Date() : undefined property var data diff --git a/internal/frontend/qml/Notifications/Notifications.qml b/internal/frontend/qml/Notifications/Notifications.qml index f3f110bf..c4302dc3 100644 --- a/internal/frontend/qml/Notifications/Notifications.qml +++ b/internal/frontend/qml/Notifications/Notifications.qml @@ -29,6 +29,13 @@ QtObject { property StatusWindow frontendStatus property SystemTrayIcon frontendTray + signal askDisableBeta() + signal askEnableBeta() + signal askEnableSplitMode(var user) + signal askDisableLocalCache() + signal askEnableLocalCache(var path) + signal askResetBridge() + enum Group { Connection = 1, Update = 2, @@ -48,12 +55,20 @@ QtObject { root.updateForceError, root.updateSilentRestartNeeded, root.updateSilentError, + root.updateIsLatestVersion, + root.disableBeta, + root.enableBeta, root.bugReportSendSuccess, root.bugReportSendError, - root.cacheAnavailable, + root.cacheUnavailable, root.cacheCantMove, root.accountChanged, - root.diskFull + root.diskFull, + root.cacheLocationChangeSuccess, + root.enableSplitMode, + root.disableLocalCache, + root.enableLocalCache, + root.resetBridge ] // Connection @@ -93,10 +108,18 @@ QtObject { action: [ Action { - text: qsTr("Update") + text: qsTr("Install update") onTriggered: { - // TODO: call update from backend + root.backend.installUpdate() + root.updateManualReady.active = false + } + }, + Action { + text: qsTr("Update manually") + + onTriggered: { + Qt.openUrlExternally(root.backend.getLandingPage()) root.updateManualReady.active = false } }, @@ -104,7 +127,6 @@ QtObject { text: qsTr("Remind me later") onTriggered: { - // TODO: start timer here root.updateManualReady.active = false } } @@ -128,14 +150,14 @@ QtObject { text: qsTr("Restart Bridge") onTriggered: { - // TODO + root.backend.restart() root.updateManualRestartNeeded.active = false } } } property Notification updateManualError: Notification { - text: qsTr("Bridge couldn’t update") + text: qsTr("Bridge couldn’t update. Please update manually.") icon: "./icons/ic-exclamation-circle-filled.svg" type: Notification.NotificationType.Warning group: Notifications.Group.Update @@ -147,19 +169,28 @@ QtObject { } } - action: Action { - text: qsTr("Update manually") + action: [ + Action { + text: qsTr("Update manually") - onTriggered: { - // TODO - root.updateManualError.active = false + onTriggered: { + Qt.openUrlExternally(root.backend.getLandingPage()) + root.updateManualError.active = false + } + }, + Action { + text: qsTr("Remind me later") + + onTriggered: { + root.updateManualReady.active = false + } } - } + ] } property Notification updateForce: Notification { text: qsTr("Update to ProtonMail Bridge") + " " + (data ? data.version : "") - description: qsTr("This version of Bridge is no longer supported, please update. Learn why. To update manually, go to: https:/protonmail.com/bridge/download") + description: qsTr("This version of Bridge is no longer supported, please update.") icon: "./icons/ic-exclamation-circle-filled.svg" type: Notification.NotificationType.Danger group: Notifications.Group.Update | Notifications.Group.Dialogs @@ -175,18 +206,26 @@ QtObject { action: [ Action { - text: qsTr("Update") + text: qsTr("Install update") onTriggered: { - // TODO: trigger update here + root.backend.installUpdate() root.updateForce.active = false } }, Action { - text: qsTr("Quite Bridge") + text: qsTr("Update manually") onTriggered: { - // TODO: quit Bridge here + Qt.openUrlExternally(root.backend.getLandingPage()) + root.updateForce.active = false + } + }, + Action { + text: qsTr("Quit Bridge") + + onTriggered: { + root.backend.quit() root.updateForce.active = false } } @@ -195,7 +234,7 @@ QtObject { property Notification updateForceError: Notification { text: qsTr("Bridge coudn’t update") - description: qsTr("You must update manually. Go to: https:/protonmail.com/bridge/download") + description: qsTr("You must update manually.") icon: "./icons/ic-exclamation-circle-filled.svg" type: Notification.NotificationType.Danger group: Notifications.Group.Update | Notifications.Group.Dialogs @@ -213,15 +252,15 @@ QtObject { text: qsTr("Update manually") onTriggered: { - // TODO: trigger update here + Qt.openUrlExternally(root.backend.getLandingPage()) root.updateForceError.active = false } }, Action { - text: qsTr("Quite Bridge") + text: qsTr("Quit Bridge") onTriggered: { - // TODO: quit Bridge here + root.backend.quit() root.updateForce.active = false } } @@ -245,7 +284,7 @@ QtObject { text: qsTr("Restart Bridge") onTriggered: { - // TODO + root.backend.restart() root.updateSilentRestartNeeded.active = false } } @@ -268,18 +307,105 @@ QtObject { text: qsTr("Update manually") onTriggered: { - // TODO + Qt.openUrlExternally(root.backend.getLandingPage()) root.updateSilentError.active = false } } } + property Notification updateIsLatestVersion: Notification { + text: qsTr("Bridge is up to date") + icon: "./icons/ic-info-circle-filled.svg" + type: Notification.NotificationType.Info + group: Notifications.Group.Update + + Connections { + target: root.backend + onUpdateIsLatestVersion: { + root.updateIsLatestVersion.active = true + } + } + + action: Action { + text: qsTr("Ok") + + onTriggered: { + root.updateIsLatestVersion.active = false + } + } + } + + property Notification disableBeta: Notification { + text: qsTr("Disable beta access?") + description: qsTr("This resets Bridge to the current release and will restart the app. Your preferences, cached data, and email client configurations will be cleared. ") + icon: "./icons/ic-exclamation-circle-filled.svg" + type: Notification.NotificationType.Warning + group: Notifications.Group.Update | Notifications.Group.Dialogs + + Connections { + target: root + onAskDisableBeta: { + root.disableBeta.active = true + } + } + + action: [ + Action { + text: qsTr("Remind me later") + + onTriggered: { + root.disableBeta.active = false + } + }, + Action { + text: qsTr("Disable and restart") + onTriggered: { + root.backend.toggleBeta(false) + root.disableBeta.loading = true + } + } + ] + } + + property Notification enableBeta: Notification { + text: qsTr("Enable beta access?") + description: qsTr("Bridge will update to the latest beta version according to your update preferences. Disabling beta access later on will reset Bridge and require you to reconfigure your client.") + icon: "./icons/ic-info-circle-filled.svg" + type: Notification.NotificationType.Info + group: Notifications.Group.Update | Notifications.Group.Dialogs + + Connections { + target: root + onAskEnableBeta: { + root.enableBeta.active = true + } + } + + action: [ + Action { + text: qsTr("Enable") + onTriggered: { + root.backend.toggleBeta(true) + root.enableBeta.active = false + } + }, + Action { + text: qsTr("Cancel") + + onTriggered: { + root.enableBeta.active = false + } + } + ] + } + + // Bug reports property Notification bugReportSendSuccess: Notification { - text: qsTr("Bug report sent") - description: qsTr("We’ve received your report, thank you! Our team will get back to you as soon as we can.") + text: qsTr("Thank you for the report. We'll get back to you as soon as we can.") + icon: "./icons/ic-info-circle-filled.svg" type: Notification.NotificationType.Success - group: Notifications.Group.Configuration | Notifications.Group.Dialogs + group: Notifications.Group.Configuration Connections { target: root.backend @@ -302,10 +428,10 @@ QtObject { } property Notification bugReportSendError: Notification { - text: qsTr("There was a problem") - description: qsTr("There was a problem with sending your report. Please try again later or contact us directly at security@protonmail.com") - type: Notification.NotificationType.Warning - group: Notifications.Group.Configuration | Notifications.Group.Dialogs + text: qsTr("Report could not be sent. Try again or email us directly.") + icon: "./icons/ic-exclamation-circle-filled.svg" + type: Notification.NotificationType.Danger + group: Notifications.Group.Configuration Connections { target: root.backend @@ -323,7 +449,7 @@ QtObject { } // Cache - property Notification cacheAnavailable: Notification { + property Notification cacheUnavailable: Notification { text: qsTr("Cache location is unavailable") description: qsTr("Check the directory or change it in your settings.") type: Notification.NotificationType.Warning @@ -331,8 +457,8 @@ QtObject { Connections { target: root.backend - onCacheAnavailable: { - root.cacheAnavailable.active = true + onCacheUnavailable: { + root.cacheUnavailable.active = true } } @@ -340,13 +466,15 @@ QtObject { Action { text: qsTr("Quit Bridge") onTriggered: { - root.cacheAnavailable.active = false + root.backend.quit() + root.cacheUnavailable.active = false } }, Action { text: qsTr("Change location") onTriggered: { - root.cacheAnavailable.active = false + root.cacheUnavailable.active = false + root.frontendMain.showLocalCacheSettings() } } ] @@ -376,6 +504,31 @@ QtObject { text: qsTr("Change location") onTriggered: { root.cacheCantMove.active = false + root.frontendMain.showLocalCacheSettings() + } + } + ] + } + + property Notification cacheLocationChangeSuccess: Notification { + text: qsTr("Cache location successfully changed") + icon: "./icons/ic-info-circle-filled.svg" + type: Notification.NotificationType.Success + group: Notifications.Group.Configuration + + Connections { + target: root.backend + onCacheLocationChangeSuccess: { + console.log("notify location changed succesfully") + root.cacheLocationChangeSuccess.active = true + } + } + + action: [ + Action { + text: qsTr("Ok") + onTriggered: { + root.cacheLocationChangeSuccess.active = false } } ] @@ -414,6 +567,7 @@ QtObject { Action { text: qsTr("Quit Bridge") onTriggered: { + root.backend.quit() root.diskFull.active = false } }, @@ -421,6 +575,171 @@ QtObject { text: qsTr("Settings") onTriggered: { root.diskFull.active = false + root.frontendMain.showLocalCacheSettings() + } + } + ] + } + + property Notification enableSplitMode: Notification { + text: qsTr("Enable split mode?") + description: qsTr("Changing between split and combined address mode will require you to delete your accounts(s) from your email client and begin the setup process from scratch.") + type: Notification.NotificationType.Warning + group: Notifications.Group.Configuration | Notifications.Group.Dialogs + + property var user + + Connections { + target: root + onAskEnableSplitMode: { + root.enableSplitMode.user = user + root.enableSplitMode.active = true + } + } + + + Connections { + target: (root && root.enableSplitMode && root.enableSplitMode.user ) ? root.enableSplitMode.user : null + onToggleSplitModeFinished: { + root.enableSplitMode.active = false + root.enableSplitMode.loading = false + } + } + + action: [ + Action { + text: qsTr("Cancel") + onTriggered: { + root.enableSplitMode.active = false + } + }, + Action { + text: qsTr("Enable split mode") + onTriggered: { + root.enableSplitMode.loading = true + root.enableSplitMode.user.toggleSplitMode(true) + } + } + ] + } + + property Notification disableLocalCache: Notification { + text: qsTr("Disable local cache?") + description: qsTr("This action will clear your local cache, including locally stored messages. Bridge will restart.") + type: Notification.NotificationType.Warning + group: Notifications.Group.Configuration | Notifications.Group.Dialogs + + Connections { + target: root + onAskDisableLocalCache: { + root.disableLocalCache.active = true + } + } + + + Connections { + target: root.backend + onChangeLocalCacheFinished: { + root.disableLocalCache.active = false + root.disableLocalCache.loading = false + } + } + + action: [ + Action { + text: qsTr("Cancel") + onTriggered: { + root.disableLocalCache.active = false + } + }, + Action { + text: qsTr("Disable and restart") + onTriggered: { + root.disableLocalCache.loading = true + root.backend.changeLocalCache(false, root.backend.diskCachePath) + } + } + ] + } + + property Notification enableLocalCache: Notification { + text: qsTr("Enable local cache?") + description: qsTr("Bridge will restart.") + type: Notification.NotificationType.Warning + group: Notifications.Group.Configuration | Notifications.Group.Dialogs + + property var path + + Connections { + target: root + onAskEnableLocalCache: { + root.enableLocalCache.active = true + root.enableLocalCache.path = path + } + } + + + Connections { + target: root.backend + onChangeLocalCacheFinished: { + root.enableLocalCache.active = false + root.enableLocalCache.loading = false + } + } + + action: [ + Action { + text: qsTr("Enable and restart") + onTriggered: { + root.enableLocalCache.loading = true + root.backend.changeLocalCache(true, root.enableLocalCache.path) + } + }, + Action { + text: qsTr("Cancel") + onTriggered: { + root.enableLocalCache.active = false + } + } + ] + } + + property Notification resetBridge: Notification { + text: qsTr("Reset Bridge?") + description: qsTr("This will clear your accounts, preferences, and cached data. You will need to reconfigure your email client. Bridge will automatically restart") + type: Notification.NotificationType.Warning + group: Notifications.Group.Configuration | Notifications.Group.Dialogs + + property var user + + Connections { + target: root + onAskResetBridge: { + root.resetBridge.active = true + } + } + + + Connections { + target: root.backend + onResetFinished: { + root.resetBridge.active = false + root.resetBridge.loading = false + } + } + + action: [ + Action { + text: qsTr("Cancel") + onTriggered: { + root.resetBridge.active = false + } + }, + Action { + text: qsTr("Reset and restart") + onTriggered: { + root.resetBridge.loading = true + root.backend.triggerReset() } } ] diff --git a/internal/frontend/qml/PortSettings.qml b/internal/frontend/qml/PortSettings.qml new file mode 100644 index 00000000..cfde2e49 --- /dev/null +++ b/internal/frontend/qml/PortSettings.qml @@ -0,0 +1,154 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.13 +import QtQuick.Controls.impl 2.13 + +import Proton 4.0 + +SettingsView { + id: root + + property bool _valuesOK: !imapField.error && !smtpField.error + property bool _valuesChanged: ( + imapField.text*1 != root.backend.portIMAP || + smtpField.text*1 != root.backend.portSMTP + ) + + Label { + colorScheme: root.colorScheme + text: qsTr("Default ports") + type: Label.Heading + Layout.fillWidth: true + } + + Label { + colorScheme: root.colorScheme + text: qsTr("Changes require reconfiguration of your email client. Bridge will automatically restart.") + type: Label.Body + color: root.colorScheme.text_weak + Layout.fillWidth: true + wrapMode: Text.WordWrap + } + + RowLayout { + spacing: 16 + + TextField { + id: imapField + colorScheme: root.colorScheme + label: qsTr("IMAP port") + Layout.preferredWidth: 160 + onEditingFinished: root.validate(imapField) + } + TextField { + id: smtpField + colorScheme: root.colorScheme + label: qsTr("SMTP port") + Layout.preferredWidth: 160 + onEditingFinished: root.validate(smtpField) + } + } + + Rectangle { + Layout.fillWidth: true + height: 1 + color: root.colorScheme.border_weak + } + + RowLayout { + spacing: 12 + + Button { + id: submitButton + colorScheme: root.colorScheme + text: qsTr("Save and restart") + enabled: root._valuesOK && root._valuesChanged + onClicked: { + submitButton.loading = true + root.submit() + } + } + + Button { + colorScheme: root.colorScheme + text: qsTr("Cancel") + onClicked: root.back() + secondary: true + } + + Connections { + target: root.backend + + onChangePortFinished: submitButton.loading = false + } + } + + onBack: { + root.parent.showGeneralSettings() + root.setDefaultValues() + } + + function validate(field) { + var num = field.text*1 + if (! (num > 1 && num < 65536) ) { + field.error = true + field.assistiveText = qsTr("Invalid port number.") + return + } + + if (imapField.text == smtpField.text) { + field.error = true + field.assistiveText = qsTr("Port numbers must be different.") + return + } + + field.error = false + field.assistiveText = "" + } + + function isPortFree(field) { + field.error = false + field.assistiveText = "" + + var num = field.text*1 + if (num == root.backend.portIMAP) return true + if (num == root.backend.portSMTP) return true + if (!root.backend.isPortFree(num)) { + field.error = true + field.assistiveText = qsTr("Port occupied.") + submitButton.loading = false + return false + } + } + + function submit(){ + submitButton.loading = true + if (!isPortFree(imapField)) return + if (!isPortFree(smtpField)) return + root.backend.changePorts(imapField.text, smtpField.text) + } + + function setDefaultValues(){ + imapField.text = backend.portIMAP + smtpField.text = backend.portSMTP + } + + Component.onCompleted: root.setDefaultValues() +} diff --git a/internal/frontend/qml/Proton/Button.qml b/internal/frontend/qml/Proton/Button.qml index f1c77c55..4ccb9983 100644 --- a/internal/frontend/qml/Proton/Button.qml +++ b/internal/frontend/qml/Proton/Button.qml @@ -246,9 +246,25 @@ T.Button { } } - border.color: control.colorScheme.border_norm + border.color: { + return control.colorScheme.border_norm + } border.width: secondary && !borderless ? 1 : 0 opacity: control.enabled || control.loading ? 1.0 : 0.5 } + + + Component.onCompleted: { + if (!control.colorScheme) { + console.trace() + var next = root + for (var i = 0; i<1000; i++) { + console.log(i, next, "colorscheme", next.colorScheme) + next = next.parent + if (!next) break + } + console.error("ColorScheme not defined") + } + } } diff --git a/internal/frontend/qml/Proton/RoundedRectangle.qml b/internal/frontend/qml/Proton/RoundedRectangle.qml index a2edbd4c..8c94d5bd 100644 --- a/internal/frontend/qml/Proton/RoundedRectangle.qml +++ b/internal/frontend/qml/Proton/RoundedRectangle.qml @@ -21,7 +21,7 @@ import QtQuick 2.8 Rectangle { id: root - color: Style.transparent + color: "transparent" property color fillColor : Style.currentStyle.background_norm property color strokeColor : Style.currentStyle.background_strong diff --git a/internal/frontend/qml/Proton/TextArea.qml b/internal/frontend/qml/Proton/TextArea.qml index fb4b0a62..4ad302a3 100644 --- a/internal/frontend/qml/Proton/TextArea.qml +++ b/internal/frontend/qml/Proton/TextArea.qml @@ -20,6 +20,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Controls.impl 2.12 import QtQuick.Templates 2.12 as T +import "." Item { id: root @@ -86,9 +87,10 @@ Item { property alias wrapMode: control.wrapMode implicitWidth: background.width - implicitHeight: control.implicitHeight + - Math.max(label.implicitHeight + label.anchors.topMargin + label.anchors.bottomMargin, hint.implicitHeight + hint.anchors.topMargin + hint.anchors.bottomMargin) + - assistiveText.implicitHeight + implicitHeight: control.implicitHeight + Math.max( + label.implicitHeight + label.anchors.topMargin + label.anchors.bottomMargin, + hint.implicitHeight + hint.anchors.topMargin + hint.anchors.bottomMargin + ) + assistiveText.implicitHeight property alias label: label.text property alias hint: hint.text @@ -96,6 +98,8 @@ Item { property bool error: false + signal editingFinished() + // Backgroud is moved away from within control as it will be clipped with scrollview Rectangle { id: background @@ -200,12 +204,16 @@ Item { T.TextArea { id: control - implicitWidth: Math.max(contentWidth + leftPadding + rightPadding, - implicitBackgroundWidth + leftInset + rightInset, - placeholder.implicitWidth + leftPadding + rightPadding) - implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, - implicitBackgroundHeight + topInset + bottomInset, - placeholder.implicitHeight + topPadding + bottomPadding) + implicitWidth: Math.max( + contentWidth + leftPadding + rightPadding, + implicitBackgroundWidth + leftInset + rightInset, + placeholder.implicitWidth + leftPadding + rightPadding + ) + implicitHeight: Math.max( + contentHeight + topPadding + bottomPadding, + implicitBackgroundHeight + topInset + bottomInset, + placeholder.implicitHeight + topPadding + bottomPadding + ) padding: 8 leftPadding: 12 @@ -216,6 +224,8 @@ Item { selectionColor: control.palette.highlight selectedTextColor: control.palette.highlightedText + onEditingFinished: root.editingFinished() + cursorDelegate: Rectangle { id: cursor width: 1 diff --git a/internal/frontend/qml/Proton/Toggle.qml b/internal/frontend/qml/Proton/Toggle.qml new file mode 100644 index 00000000..2064b3b3 --- /dev/null +++ b/internal/frontend/qml/Proton/Toggle.qml @@ -0,0 +1,107 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.13 +import QtQuick.Controls.impl 2.13 + +RowLayout{ + id: root + property var colorScheme + property bool checked + property bool disabled + property bool hovered + property bool loading + + signal clicked + + Rectangle { + id: indicator + implicitWidth: 40 + implicitHeight: 24 + + radius: 20 + color: { + if (root.loading) return "transparent" + if (root.disabled) return root.colorScheme.background_strong + return root.colorScheme.background_norm + } + border { + width: 1 + color: (root.disabled || root.loading) ? "transparent" : colorScheme.field_norm + } + + Rectangle { + anchors.verticalCenter: indicator.verticalCenter + anchors.left: indicator.left + anchors.leftMargin: root.checked ? 16 : 0 + width: 24 + height: 24 + radius: 12 + color: { + if (root.loading) return "transparent" + if (root.disabled) return root.colorScheme.field_disabled + + if (root.checked) { + if (root.hovered) return root.colorScheme.interaction_norm_hover + return root.colorScheme.interaction_norm + } else { + if (root.hovered) return root.colorScheme.field_hover + return root.colorScheme.field_norm + } + } + + ColorImage { + anchors.centerIn: parent + source: "../icons/ic-check.svg" + color: root.colorScheme.background_norm + height: root.colorScheme.body_font_size + visible: root.checked + } + } + + ColorImage { + id: loader + anchors.centerIn: parent + source: "../icons/Loader_16.svg" + color: root.colorScheme.text_norm + height: root.colorScheme.body_font_size + visible: root.loading + + RotationAnimation { + target: loader + loops: Animation.Infinite + duration: 1000 + from: 0 + to: 360 + direction: RotationAnimation.Clockwise + running: root.loading + } + } + + MouseArea { + anchors.fill: indicator + hoverEnabled: true + onEntered: {root.hovered = true } + onExited: {root.hovered = false } + onClicked: { root.clicked();} + onPressed: {root.hovered = true } + onReleased: { root.hovered = containsMouse } + } + } +} diff --git a/internal/frontend/qml/Proton/qmldir b/internal/frontend/qml/Proton/qmldir index 4a0b011e..a2942c98 100644 --- a/internal/frontend/qml/Proton/qmldir +++ b/internal/frontend/qml/Proton/qmldir @@ -34,3 +34,4 @@ RoundedRectangle 4.0 RoundedRectangle.qml Switch 4.0 Switch.qml TextArea 4.0 TextArea.qml TextField 4.0 TextField.qml +Toggle 4.0 Toggle.qml diff --git a/internal/frontend/qml/SMTPSettings.qml b/internal/frontend/qml/SMTPSettings.qml new file mode 100644 index 00000000..d03642e9 --- /dev/null +++ b/internal/frontend/qml/SMTPSettings.qml @@ -0,0 +1,120 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.13 +import QtQuick.Controls.impl 2.13 + +import Proton 4.0 + +SettingsView { + id: root + + Label { + colorScheme: root.colorScheme + text: qsTr("SMTP connection mode") + type: Label.Heading + Layout.fillWidth: true + } + + Label { + colorScheme: root.colorScheme + text: qsTr("Changes require reconfiguration of email client. Bridge will automatically restart.") + type: Label.Body + color: root.colorScheme.text_weak + Layout.fillWidth: true + Layout.maximumWidth: this.parent.Layout.maximumWidth + wrapMode: Text.WordWrap + } + + ColumnLayout { + spacing: 16 + + ButtonGroup{ id: protocolSelection } + + Label { + colorScheme: root.colorScheme + text: qsTr("SMTP connection security") + } + + RadioButton { + id: sslButton + colorScheme: root.colorScheme + ButtonGroup.group: protocolSelection + text: qsTr("SSL") + } + + RadioButton { + id: starttlsButton + colorScheme: root.colorScheme + ButtonGroup.group: protocolSelection + text: qsTr("STARTLS") + } + } + + Rectangle { + Layout.fillWidth: true + height: 1 + color: root.colorScheme.border_weak + } + + RowLayout { + spacing: 12 + + Button { + id: submitButton + colorScheme: root.colorScheme + text: qsTr("Save and restart") + onClicked: { + submitButton.loading = true + root.submit() + } + } + + Button { + colorScheme: root.colorScheme + text: qsTr("Cancel") + onClicked: root.back() + secondary: true + } + + Connections { + target: root.backend + + onToggleUseSSLFinished: submitButton.loading = false + } + } + + onBack: { + root.parent.showGeneralSettings() + root.setDefaultValues() + } + + function submit(){ + submitButton.loading = true + root.backend.toggleUseSSLforSMTP(sslButton.checked) + } + + function setDefaultValues(){ + sslButton.checked = root.backend.useSSLforSMTP + starttlsButton.checked = !root.backend.useSSLforSMTP + } + + + Component.onCompleted: root.setDefaultValues() +} diff --git a/internal/frontend/qml/SettingsItem.qml b/internal/frontend/qml/SettingsItem.qml new file mode 100644 index 00000000..320f3387 --- /dev/null +++ b/internal/frontend/qml/SettingsItem.qml @@ -0,0 +1,105 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.12 + +import Proton 4.0 + +ColumnLayout { + id: root + property var colorScheme + + property string text: "Text" + property string actionText: "Action" + property string actionIcon: "" + property string description: "Lorem ipsum dolor sit amet" + property var type: SettingsItem.ActionType.Toggle + + property bool checked: true + property bool disabled: false + property bool loading: false + + signal clicked + + spacing: 20 + + Layout.fillWidth: true + Layout.maximumWidth: root.parent.Layout.maximumWidth + + enum ActionType { + Toggle = 1, Button = 2, PrimaryButton = 3 + } + + RowLayout { + Layout.fillWidth: true + + ColumnLayout { + Label { + id:mainLabel + colorScheme: root.colorScheme + text: root.text + type: Label.Body_semibold + } + + Label { + Layout.minimumWidth: mainLabel.width + Layout.maximumWidth: root.Layout.maximumWidth - root.spacing - ( + toggle.visible ? toggle.width : button.width + ) + + wrapMode: Text.WordWrap + colorScheme: root.colorScheme + text: root.description + color: root.colorScheme.text_weak + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + Toggle { + id: toggle + colorScheme: root.colorScheme + visible: root.type == SettingsItem.ActionType.Toggle + + checked: root.checked + loading: root.loading + onClicked: { if (!root.loading) root.clicked() } + } + + Button { + id: button + colorScheme: root.colorScheme + visible: root.type == SettingsItem.Button || root.type == SettingsItem.PrimaryButton + text: root.actionText + (root.actionIcon != "" ? " " : "") + loading: root.loading + icon.source: root.actionIcon + onClicked: { if (!root.loading) root.clicked() } + secondary: root.type != SettingsItem.PrimaryButton + } + } + + Rectangle { + Layout.fillWidth: true + color: colorScheme.border_weak + height: 1 + } +} diff --git a/internal/frontend/qml/SettingsView.qml b/internal/frontend/qml/SettingsView.qml new file mode 100644 index 00000000..28f31e90 --- /dev/null +++ b/internal/frontend/qml/SettingsView.qml @@ -0,0 +1,71 @@ +// 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.Layouts 1.12 +import QtQuick.Controls 2.13 +import QtQuick.Controls.impl 2.13 + +import Proton 4.0 + +ScrollView { + id: root + + property var colorScheme + property var backend + default property alias items: content.children + + signal back() + + property int _leftRightMargins: 64 + property int _topBottomMargins: 68 + property int _spacing: 22 + + clip: true + contentWidth: pane.width + contentHeight: pane.height + + RowLayout{ + id: pane + width: root.width + + ColumnLayout { + id: content + spacing: root._spacing + Layout.maximumWidth: root.width - 2*root._leftRightMargins + Layout.fillWidth: true + Layout.topMargin: root._topBottomMargins + Layout.bottomMargin: root._topBottomMargins + Layout.leftMargin: root._leftRightMargins + Layout.rightMargin: root._leftRightMargins + } + } + + Button { + anchors { + top: parent.top + left: parent.left + topMargin: 10 + leftMargin: 18 + } + colorScheme: root.colorScheme + onClicked: root.back() + icon.source: "icons/ic-arrow-left.svg" + secondary: true + horizontalPadding: 8 + } +} diff --git a/internal/frontend/qml/SetupGuide.qml b/internal/frontend/qml/SetupGuide.qml index ae3b902e..5799d868 100644 --- a/internal/frontend/qml/SetupGuide.qml +++ b/internal/frontend/qml/SetupGuide.qml @@ -30,12 +30,14 @@ Item { property var backend property var user + property string address signal dismissed() implicitHeight: children[0].implicitHeight implicitWidth: children[0].implicitWidth + RowLayout { anchors.fill: parent spacing: 0 @@ -56,7 +58,7 @@ Item { Label { colorScheme: root.colorScheme - text: user ? user.username : "" + text: address color: root.colorScheme.text_weak type: Label.LabelType.Lead } @@ -80,30 +82,50 @@ Item { Repeater { model: clients - ColumnLayout { - RowLayout { - Layout.topMargin: 12 - Layout.bottomMargin: 12 - Layout.leftMargin: 16 - Layout.rightMargin: 16 + Rectangle { + implicitWidth: clientRow.width + implicitHeight: clientRow.height - ColorImage { - source: model.iconSource - height: 36 + ColumnLayout { + id: clientRow + + RowLayout { + Layout.topMargin: 12 + Layout.bottomMargin: 12 + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + ColorImage { + source: model.iconSource + height: 36 + } + + Label { + colorScheme: root.colorScheme + Layout.leftMargin: 12 + text: model.name + type: Label.LabelType.Body + } } - Label { - colorScheme: root.colorScheme - Layout.leftMargin: 12 - text: model.name - type: Label.LabelType.Body + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: root.colorScheme.border_weak } } - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - color: root.colorScheme.border_weak + + MouseArea { + anchors.fill: parent + onClicked: { + if (model.name != "Apple Mail") { + console.log(" TODO configure ", model.name) + return + } + root.user.configureAppleMail(root.address) + root.dismissed() + } } } } diff --git a/internal/frontend/qml/SignIn.qml b/internal/frontend/qml/SignIn.qml index 8698753b..59db1305 100644 --- a/internal/frontend/qml/SignIn.qml +++ b/internal/frontend/qml/SignIn.qml @@ -42,18 +42,9 @@ Item { property var backend property var window - // in case of adding new account this property should be undefined - property var user + property alias username: usernameTextField.text state: "Page 1" - onUserChanged: { - stackLayout.currentIndex = 0 - loginNormalLayout.reset() - passwordTextField.text = "" - login2FALayout.reset() - login2PasswordLayout.reset() - } - onLoginAbort: { stackLayout.currentIndex = 0 loginNormalLayout.reset() @@ -78,15 +69,15 @@ Item { } Connections { - target: user !== undefined ? user : root.backend + target: root.backend onLoginUsernamePasswordError: { console.assert(stackLayout.currentIndex == 0, "Unexpected loginUsernamePasswordError") console.assert(signInButton.loading == true, "Unexpected loginUsernamePasswordError") stackLayout.loginFailed() - errorLabel.text = qsTr("Your email and/or password are incorrect") - + if (errorMsg!="") errorLabel.text = errorMsg + else errorLabel.text = qsTr("Your email and/or password are incorrect") } onLoginFreeUserError: { @@ -152,6 +143,14 @@ Item { errorLabel.text = qsTr("Incorrect login credentials. Please try again.") passwordTextField.text = "" } + + onLoginFinished: { + stackLayout.currentIndex = 0 + loginNormalLayout.reset() + passwordTextField.text = "" + login2FALayout.reset() + login2PasswordLayout.reset() + } } ColumnLayout { @@ -218,8 +217,6 @@ Item { id: usernameTextField label: qsTr("Username or email") - text: user !== undefined ? user.username : "" - Layout.fillWidth: true Layout.topMargin: 24 @@ -304,12 +301,7 @@ Item { enabled = false loading = true - if (root.user !== undefined) { - root.user.login(usernameTextField.text, passwordTextField.text) - return - } - - root.login(usernameTextField.text, passwordTextField.text) + root.login(usernameTextField.text, Qt.btoa(passwordTextField.text)) } } @@ -394,12 +386,7 @@ Item { enabled = false loading = true - if (root.user !== undefined) { - root.user.login2FA(usernameTextField.text, twoFactorPasswordTextField.text) - return - } - - root.login2FA(usernameTextField.text, twoFactorPasswordTextField.text) + root.login2FA(usernameTextField.text, Qt.btoa(twoFactorPasswordTextField.text)) } } } @@ -471,12 +458,7 @@ Item { enabled = false loading = true - if (root.user !== undefined) { - root.user.login2Password(usernameTextField.text, secondPasswordTextField.text) - return - } - - root.login2Password(usernameTextField.text, secondPasswordTextField.text) + root.login2Password(usernameTextField.text, Qt.btoa(secondPasswordTextField.text)) } } } diff --git a/internal/frontend/qml/StatusWindow.qml b/internal/frontend/qml/StatusWindow.qml index d74ca461..a2897422 100644 --- a/internal/frontend/qml/StatusWindow.qml +++ b/internal/frontend/qml/StatusWindow.qml @@ -22,20 +22,16 @@ import QtQuick.Layouts 1.12 import QtQuick.Controls 2.13 import Proton 4.0 -import ProtonBackend 1.0 import Notifications 1.0 -// Because of https://bugreports.qt.io/browse/QTBUG-69777 and other bugs alike it is impossible -// to use Window with flags: Qt.Popup here since it won't close by it's own on click outside. -PopupWindow { +Window { id: root title: "ProtonMail Bridge" height: contentLayout.implicitHeight width: contentLayout.implicitWidth - minimumHeight: 201 - minimumWidth: 448 + flags: Qt.FramelessWindowHint property ColorScheme colorScheme: ProtonStyle.currentStyle @@ -47,15 +43,19 @@ PopupWindow { signal showMainWindow() signal showHelp() signal showSettings() + signal showSignIn(string username) signal quit() ColumnLayout { id: contentLayout + Layout.minimumHeight: 201 + anchors.fill: parent spacing: 0 ColumnLayout { + Layout.minimumWidth: 448 Layout.fillWidth: true spacing: 0 @@ -76,13 +76,13 @@ PopupWindow { } switch (statusItem.activeNotification.type) { - case Notification.NotificationType.Danger: + case Notification.NotificationType.Danger: return root.colorScheme.signal_danger - case Notification.NotificationType.Warning: + case Notification.NotificationType.Warning: return root.colorScheme.signal_warning - case Notification.NotificationType.Success: + case Notification.NotificationType.Success: return root.colorScheme.signal_success - case Notification.NotificationType.Info: + case Notification.NotificationType.Info: return root.colorScheme.signal_info } } @@ -149,8 +149,8 @@ PopupWindow { Layout.fillHeight: true Layout.maximumHeight: accountListView.count ? - accountListView.contentHeight / accountListView.count * 3 + accountListView.anchors.topMargin + accountListView.anchors.bottomMargin : - Number.POSITIVE_INFINITY + accountListView.contentHeight / accountListView.count * 3 + accountListView.anchors.topMargin + accountListView.anchors.bottomMargin : + Number.POSITIVE_INFINITY color: root.colorScheme.background_norm clip: true @@ -171,13 +171,17 @@ PopupWindow { interactive: contentHeight > parent.height snapMode: ListView.SnapToItem + boundsBehavior: Flickable.StopAtBounds delegate: Item { + id: viewItem width: ListView.view.width implicitHeight: children[0].implicitHeight implicitWidth: children[0].implicitWidth + property var user: root.backend.users.get(index) + RowLayout { spacing: 0 anchors.fill: parent @@ -187,15 +191,19 @@ PopupWindow { Layout.margins: 12 - user: modelData + user: viewItem.user colorScheme: root.colorScheme - } + Button { Layout.margins: 12 colorScheme: root.colorScheme - visible: true - text: "test" + visible: !viewItem.user.loggedIn + text: qsTr("Sign in") + onClicked: { + root.showSignIn(viewItem.username) + root.visible = false + } } } } @@ -297,4 +305,8 @@ PopupWindow { } } } + + onActiveChanged: { + if (!active) root.close() + } } diff --git a/internal/frontend/qml/WelcomeGuide.qml b/internal/frontend/qml/WelcomeGuide.qml index 26f56ff9..489092a2 100644 --- a/internal/frontend/qml/WelcomeGuide.qml +++ b/internal/frontend/qml/WelcomeGuide.qml @@ -239,7 +239,7 @@ Item { root.loginAbort(username) } - user: (backend.users.count === 1 && backend.users.get(0).loggedIn === false) ? backend.users.get(0) : undefined + username: (backend.users.count === 1 && backend.users.get(0).loggedIn === false) ? backend.users.get(0).username : "" backend: root.backend window: root.window } diff --git a/internal/frontend/qml/icons/ic-chevron-down.svg b/internal/frontend/qml/icons/ic-chevron-down.svg new file mode 100644 index 00000000..eda8be41 --- /dev/null +++ b/internal/frontend/qml/icons/ic-chevron-down.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/internal/frontend/qml/icons/ic-chevron-up.svg b/internal/frontend/qml/icons/ic-chevron-up.svg new file mode 100644 index 00000000..a190565d --- /dev/null +++ b/internal/frontend/qml/icons/ic-chevron-up.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/internal/frontend/qml/icons/ic-copy.svg b/internal/frontend/qml/icons/ic-copy.svg new file mode 100644 index 00000000..f27164ab --- /dev/null +++ b/internal/frontend/qml/icons/ic-copy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/internal/frontend/qml/icons/ic-external-link.svg b/internal/frontend/qml/icons/ic-external-link.svg new file mode 100644 index 00000000..e2abee05 --- /dev/null +++ b/internal/frontend/qml/icons/ic-external-link.svg @@ -0,0 +1,3 @@ + + + diff --git a/internal/frontend/qml/icons/ic-info.svg b/internal/frontend/qml/icons/ic-info.svg new file mode 100644 index 00000000..f9eacb9a --- /dev/null +++ b/internal/frontend/qml/icons/ic-info.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/internal/frontend/qml/icons/ic-trash.svg b/internal/frontend/qml/icons/ic-trash.svg new file mode 100644 index 00000000..516f894f --- /dev/null +++ b/internal/frontend/qml/icons/ic-trash.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/internal/frontend/qt/dockicon/DockIcon.h b/internal/frontend/qt/dockicon/DockIcon.h new file mode 100644 index 00000000..e4310044 --- /dev/null +++ b/internal/frontend/qt/dockicon/DockIcon.h @@ -0,0 +1,24 @@ +// 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 . + +// +build darwin +// +build build_qt + +#include + +void SetDockIconVisibleState(bool visible); +bool GetDockIconVisibleState(); diff --git a/internal/frontend/qt/dockicon/DockIcon.m b/internal/frontend/qt/dockicon/DockIcon.m new file mode 100644 index 00000000..82fdc667 --- /dev/null +++ b/internal/frontend/qt/dockicon/DockIcon.m @@ -0,0 +1,42 @@ +// 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 . + +// +build darwin +// +build build_qt + +#include "DockIcon.h" +#include + +void SetDockIconVisibleState(bool visible) { + if (visible) { + [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; + return; + } else { + [NSApp setActivationPolicy: NSApplicationActivationPolicyAccessory]; + return; + } +} + +bool GetDockIconVisibleState() { + switch ([NSApp activationPolicy]) { + case NSApplicationActivationPolicyAccessory: + case NSApplicationActivationPolicyProhibited: + return false; + case NSApplicationActivationPolicyRegular: + return true; + } +} diff --git a/internal/frontend/qt/dockicon/dockicon_darwin.go b/internal/frontend/qt/dockicon/dockicon_darwin.go new file mode 100644 index 00000000..a6352e55 --- /dev/null +++ b/internal/frontend/qt/dockicon/dockicon_darwin.go @@ -0,0 +1,33 @@ +// 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 . + +// +build darwin +// +build build_qt + +package dockicon + +// #cgo CFLAGS: -x objective-c +// #cgo LDFLAGS: -framework Cocoa +// #include "DockIcon.h" +import "C" + +func SetDockIconVisibleState(visible bool) { + C.SetDockIconVisibleState(C.bool(visible)) +} +func GetDockIconVisibleState() bool { + return bool(C.GetDockIconVisibleState()) +} diff --git a/internal/frontend/qt/dockicon/dockicon_default.go b/internal/frontend/qt/dockicon/dockicon_default.go new file mode 100644 index 00000000..d2927587 --- /dev/null +++ b/internal/frontend/qt/dockicon/dockicon_default.go @@ -0,0 +1,26 @@ +// 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 . + +// +build !darwin +// +build build_qt + +package dockicon + +func SetDockIconVisibleState(visible bool) {} +func GetDockIconVisibleState() bool { + return true +} diff --git a/internal/frontend/qt/frontend.go b/internal/frontend/qt/frontend.go new file mode 100644 index 00000000..3cba590a --- /dev/null +++ b/internal/frontend/qt/frontend.go @@ -0,0 +1,146 @@ +// 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 . + +// +build build_qt + +// Package qt provides communication between Qt/QML frontend and Go backend +package qt + +import ( + "fmt" + "sync" + + "github.com/ProtonMail/go-autostart" + "github.com/ProtonMail/proton-bridge/internal/config/settings" + "github.com/ProtonMail/proton-bridge/internal/config/useragent" + "github.com/ProtonMail/proton-bridge/internal/frontend/types" + "github.com/ProtonMail/proton-bridge/internal/locations" + "github.com/ProtonMail/proton-bridge/internal/updater" + "github.com/ProtonMail/proton-bridge/pkg/listener" + "github.com/ProtonMail/proton-bridge/pkg/pmapi" + "github.com/sirupsen/logrus" + "github.com/therecipe/qt/qml" + "github.com/therecipe/qt/widgets" +) + +type FrontendQt struct { + programName, programVersion string + + panicHandler types.PanicHandler + locations *locations.Locations + settings *settings.Settings + eventListener listener.Listener + updater types.Updater + userAgent *useragent.UserAgent + bridge types.Bridger + noEncConfirmator types.NoEncConfirmator + autostart *autostart.App + restarter types.Restarter + + authClient pmapi.Client + auth *pmapi.Auth + password []byte + + newVersionInfo updater.VersionInfo + + log *logrus.Entry + usersMtx sync.Mutex + + app *widgets.QApplication + engine *qml.QQmlApplicationEngine + qml *QMLBackend +} + +func New( + version, + buildVersion, + programName string, + showWindowOnStart bool, + panicHandler types.PanicHandler, + locations *locations.Locations, + settings *settings.Settings, + eventListener listener.Listener, + updater types.Updater, + userAgent *useragent.UserAgent, + bridge types.Bridger, + _ types.NoEncConfirmator, + autostart *autostart.App, + restarter types.Restarter, +) *FrontendQt { + return &FrontendQt{ + programName: "Proton Mail Bridge", + programVersion: version, + log: logrus.WithField("pkg", "frontend/qt"), + + panicHandler: panicHandler, + locations: locations, + settings: settings, + eventListener: eventListener, + updater: updater, + userAgent: userAgent, + bridge: bridge, + autostart: autostart, + restarter: restarter, + } +} + +func (f *FrontendQt) Loop() error { + err := f.initiateQtApplication() + if err != nil { + return err + } + + go func() { + defer f.panicHandler.HandlePanic() + f.watchEvents() + }() + + if ret := f.app.Exec(); ret != 0 { + err := fmt.Errorf("Event loop ended with return value: %v", ret) + f.log.Warn("App exec", err) + return err + } + + return nil +} + +func (f *FrontendQt) NotifyManualUpdate(version updater.VersionInfo, canInstall bool) { + if canInstall { + f.qml.UpdateManualReady(version.Version.String()) + } else { + f.qml.UpdateManualError() + } +} + +func (f *FrontendQt) SetVersion(version updater.VersionInfo) { + f.newVersionInfo = version + f.qml.SetReleaseNotesLink(version.ReleaseNotesPage) + f.qml.SetLandingPageLink(version.LandingPage) +} + +func (f *FrontendQt) NotifySilentUpdateInstalled() { + f.qml.UpdateSilentRestartNeeded() +} + +func (f *FrontendQt) NotifySilentUpdateError(err error) { + f.log.WithError(err).Warn("Update failed, asking for manual.") + f.qml.UpdateManualError() +} + +func (f *FrontendQt) WaitUntilFrontendIsReady() { + // TODO: Implement +} diff --git a/internal/frontend/qt/frontend_events.go b/internal/frontend/qt/frontend_events.go new file mode 100644 index 00000000..13631ec4 --- /dev/null +++ b/internal/frontend/qt/frontend_events.go @@ -0,0 +1,85 @@ +// 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 . + +// +build build_qt + +// Package qt provides communication between Qt/QML frontend and Go backend +package qt + +import ( + "strings" + + "github.com/ProtonMail/proton-bridge/internal/events" +) + +func (f *FrontendQt) watchEvents() { + f.WaitUntilFrontendIsReady() + + errorCh := f.eventListener.ProvideChannel(events.ErrorEvent) + credentialsErrorCh := f.eventListener.ProvideChannel(events.CredentialsErrorEvent) + noActiveKeyForRecipientCh := f.eventListener.ProvideChannel(events.NoActiveKeyForRecipientEvent) + internetOffCh := f.eventListener.ProvideChannel(events.InternetOffEvent) + internetOnCh := f.eventListener.ProvideChannel(events.InternetOnEvent) + secondInstanceCh := f.eventListener.ProvideChannel(events.SecondInstanceEvent) + restartBridgeCh := f.eventListener.ProvideChannel(events.RestartBridgeEvent) + addressChangedCh := f.eventListener.ProvideChannel(events.AddressChangedEvent) + addressChangedLogoutCh := f.eventListener.ProvideChannel(events.AddressChangedLogoutEvent) + logoutCh := f.eventListener.ProvideChannel(events.LogoutEvent) + updateApplicationCh := f.eventListener.ProvideChannel(events.UpgradeApplicationEvent) + userChangedCh := f.eventListener.ProvideChannel(events.UserRefreshEvent) + certIssue := f.eventListener.ProvideChannel(events.TLSCertIssue) + + for { + select { + case errorDetails := <-errorCh: + if strings.Contains(errorDetails, "IMAP failed") { + f.qml.PortIssueIMAP() + } + if strings.Contains(errorDetails, "SMTP failed") { + f.qml.PortIssueSMTP() + } + case <-credentialsErrorCh: + f.qml.NotifyHasNoKeychain() + case email := <-noActiveKeyForRecipientCh: + f.qml.NoActiveKeyForRecipient(email) + case <-internetOffCh: + f.qml.InternetOff() + case <-internetOnCh: + f.qml.InternetOn() + case <-secondInstanceCh: + f.qml.ShowMainWindow() + case <-restartBridgeCh: + f.restart() + case address := <-addressChangedCh: + f.qml.AddressChanged(address) + case address := <-addressChangedLogoutCh: + f.qml.AddressChangedLogout(address) + case userID := <-logoutCh: + user, err := f.bridge.GetUser(userID) + if err != nil { + return + } + f.qml.UserDisconnected(user.Username()) + case <-updateApplicationCh: + f.updateForce() + case userID := <-userChangedCh: + f.userChanged(userID) + case <-certIssue: + f.qml.ApiCertIssue() + } + } +} diff --git a/internal/frontend/qt/frontend_help.go b/internal/frontend/qt/frontend_help.go new file mode 100644 index 00000000..e105e0f4 --- /dev/null +++ b/internal/frontend/qt/frontend_help.go @@ -0,0 +1,45 @@ +// 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 . + +// +build build_qt + +package qt + +func (f *FrontendQt) setVersion() { + f.qml.SetVersion(f.programVersion) +} + +func (f *FrontendQt) setLogsPath() { + path, err := f.locations.ProvideLogsPath() + if err != nil { + f.log.WithError(err).Error("Cannot update path folder") + return + } + f.qml.SetLogsPath(path) +} + +func (f *FrontendQt) setLicensePath() { + f.qml.SetLicensePath(f.locations.GetLicenseFilePath()) +} + +func (f *FrontendQt) setCurrentEmailClient() { + f.qml.SetCurrentEmailClient(f.userAgent.String()) +} + +func (f *FrontendQt) reportBug(description, address, emailClient string, includeLogs bool) { + //TODO +} diff --git a/internal/frontend/qt/frontend_init.go b/internal/frontend/qt/frontend_init.go new file mode 100644 index 00000000..1d213fb8 --- /dev/null +++ b/internal/frontend/qt/frontend_init.go @@ -0,0 +1,71 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "errors" + qmlLog "github.com/ProtonMail/proton-bridge/internal/frontend/qt/log" + "github.com/therecipe/qt/core" + "github.com/therecipe/qt/qml" + "github.com/therecipe/qt/quickcontrols2" + "github.com/therecipe/qt/widgets" + "os" +) + +func (f *FrontendQt) initiateQtApplication() error { + qmlLog.InstallMessageHandler() + + f.app = widgets.NewQApplication(len(os.Args), os.Args) + + core.QCoreApplication_SetApplicationName(f.programName) + core.QCoreApplication_SetApplicationVersion(f.programVersion) + + // High DPI scaling for windows. + core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, false) + // Software OpenGL: to avoid dedicated GPU. + core.QCoreApplication_SetAttribute(core.Qt__AA_UseSoftwareOpenGL, true) + + // Bridge runs background, no window is needed to be opened. + f.app.SetQuitOnLastWindowClosed(false) + + // QML Engine and path + f.engine = qml.NewQQmlApplicationEngine(f.app) + + f.qml = NewQMLBackend(nil) + f.qml.setup(f) + f.engine.RootContext().SetContextProperty("go", f.qml) + + f.engine.AddImportPath("qrc:/qml/") + f.engine.AddPluginPath("qrc:/qml/") + + // Add style: if colorScheme / style is forgotten we should fallback to + // default style and should be Proton + quickcontrols2.QQuickStyle_AddStylePath("qrc:/qml/") + quickcontrols2.QQuickStyle_SetStyle("Proton") + + f.engine.Load(core.NewQUrl3("qrc:/qml/Bridge.qml", 0)) + + // Check QML is loaded properly. + if len(f.engine.RootObjects()) == 0 { + return errors.New("QML not loaded properly") + } + + return nil +} diff --git a/internal/frontend/qt/frontend_nogui.go b/internal/frontend/qt/frontend_nogui.go new file mode 100644 index 00000000..dfe96f03 --- /dev/null +++ b/internal/frontend/qt/frontend_nogui.go @@ -0,0 +1,83 @@ +// 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 . + +// +build !build_qt + +package qt + +import ( + "fmt" + "net/http" + + "github.com/ProtonMail/go-autostart" + "github.com/ProtonMail/proton-bridge/internal/config/settings" + "github.com/ProtonMail/proton-bridge/internal/config/useragent" + "github.com/ProtonMail/proton-bridge/internal/frontend/types" + "github.com/ProtonMail/proton-bridge/internal/locations" + "github.com/ProtonMail/proton-bridge/internal/updater" + "github.com/ProtonMail/proton-bridge/pkg/listener" + "github.com/sirupsen/logrus" +) + +var log = logrus.WithField("pkg", "frontend-nogui") //nolint[gochecknoglobals] + +type FrontendHeadless struct{} + +func New( + version, + buildVersion, + programName string, + showWindowOnStart bool, + panicHandler types.PanicHandler, + locations *locations.Locations, + settings *settings.Settings, + eventListener listener.Listener, + updater types.Updater, + userAgent *useragent.UserAgent, + bridge types.Bridger, + noEncConfirmator types.NoEncConfirmator, + autostart *autostart.App, + restarter types.Restarter, +) *FrontendHeadless { + return &FrontendHeadless{} +} + +func (s *FrontendHeadless) Loop() error { + log.Info("Check status on localhost:8081") + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Bridge is running") + }) + return http.ListenAndServe(":8081", nil) +} + +func (s *FrontendHeadless) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) { + // NOTE: Save the update somewhere so that it can be installed when user chooses "install now". +} + +func (s *FrontendHeadless) WaitUntilFrontendIsReady() { +} + +func (s *FrontendHeadless) SetVersion(update updater.VersionInfo) { +} + +func (s *FrontendHeadless) NotifySilentUpdateInstalled() { +} + +func (s *FrontendHeadless) NotifySilentUpdateError(err error) { +} + +func (s *FrontendHeadless) InstanceExistAlert() {} diff --git a/internal/frontend/qt/frontend_settings.go b/internal/frontend/qt/frontend_settings.go new file mode 100644 index 00000000..1b335659 --- /dev/null +++ b/internal/frontend/qt/frontend_settings.go @@ -0,0 +1,151 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "time" + + "github.com/ProtonMail/proton-bridge/internal/config/settings" + "github.com/ProtonMail/proton-bridge/internal/frontend/clientconfig" + "github.com/ProtonMail/proton-bridge/pkg/keychain" + "github.com/ProtonMail/proton-bridge/pkg/ports" +) + +func (f *FrontendQt) setIsDiskCacheEnabled() { + //TODO +} + +func (f *FrontendQt) setDiskCachePath() { + //TODO +} + +func (f *FrontendQt) changeLocalCache(enableDiskCache bool, diskCachePath string) { + //TODO +} + +func (f *FrontendQt) setIsAutostartOn() { + f.qml.SetIsAutostartOn(f.autostart.IsEnabled()) +} + +func (f *FrontendQt) toggleAutostart(makeItEnabled bool) { + defer f.qml.ToggleAutostartFinished() + if makeItEnabled == f.autostart.IsEnabled() { + f.setIsAutostartOn() + return + } + + var err error + if makeItEnabled { + err = f.autostart.Enable() + } else { + err = f.autostart.Disable() + } + f.setIsAutostartOn() + + if err != nil { + f.log. + WithField("makeItEnabled", makeItEnabled). + WithField("isEnabled", f.qml.IsAutostartOn()). + WithError(err). + Error("Autostart change failed") + } +} + +func (f *FrontendQt) toggleDoH(makeItEnabled bool) { + if f.settings.GetBool(settings.AllowProxyKey) == makeItEnabled { + f.qml.SetIsDoHEnabled(makeItEnabled) + return + } + f.settings.SetBool(settings.AllowProxyKey, makeItEnabled) + f.restart() +} + +func (f *FrontendQt) toggleUseSSLforSMTP(makeItEnabled bool) { + if f.settings.GetBool(settings.SMTPSSLKey) == makeItEnabled { + f.qml.SetUseSSLforSMTP(makeItEnabled) + return + } + f.settings.SetBool(settings.SMTPPortKey, makeItEnabled) + f.restart() +} + +func (f *FrontendQt) changePorts(imapPort, smtpPort int) { + f.settings.SetInt(settings.IMAPPortKey, imapPort) + f.settings.SetInt(settings.SMTPPortKey, smtpPort) + f.restart() +} + +func (f *FrontendQt) isPortFree(port int) bool { + return ports.IsPortFree(port) +} + +func (f *FrontendQt) configureAppleMail(userID, address string) { + user, err := f.bridge.GetUser(userID) + if err != nil { + f.log.WithField("userID", userID).Error("Cannot configure AppleMail for user") + return + } + + needRestart, err := clientconfig.ConfigureAppleMail(user, address, f.settings) + if err != nil { + f.log.WithError(err).Error("Apple Mail config failed") + } + + if needRestart { + // There is delay needed for external window to open + time.Sleep(2 * time.Second) + f.restart() + } +} + +func (f *FrontendQt) triggerReset() { + defer f.qml.ResetFinished() + //TODO + f.restart() +} + +func (f *FrontendQt) setKeychain() { + availableKeychain := []string{} + for chain := range keychain.Helpers { + availableKeychain = append(availableKeychain, chain) + } + f.qml.SetAvailableKeychain(availableKeychain) + f.qml.SetSelectedKeychain(f.bridge.GetKeychainApp()) +} + +func (f *FrontendQt) selectKeychain(wantKeychain string) { + if f.bridge.GetKeychainApp() == wantKeychain { + return + } + + f.bridge.SetKeychainApp(wantKeychain) + f.restart() +} + +func (f *FrontendQt) restart() { + f.log.Info("Restarting bridge") + f.restarter.SetToRestart() + f.app.Exit(0) +} + +func (f *FrontendQt) quit() { + f.log.Warn("Your wish is my command.. I quit!") + f.app.Exit(0) +} diff --git a/internal/frontend/qt/frontend_updates.go b/internal/frontend/qt/frontend_updates.go new file mode 100644 index 00000000..9f02e448 --- /dev/null +++ b/internal/frontend/qt/frontend_updates.go @@ -0,0 +1,130 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "sync" + + "github.com/ProtonMail/proton-bridge/internal/config/settings" + "github.com/ProtonMail/proton-bridge/internal/updater" +) + +var checkingUpdates = sync.Mutex{} + +func (f *FrontendQt) checkUpdates() error { + version, err := f.updater.Check() + if err != nil { + return err + } + + f.SetVersion(version) + return nil +} + +func (f *FrontendQt) checkUpdatesAndNotify(isRequestFromUser bool) { + checkingUpdates.Lock() + defer checkingUpdates.Lock() + defer f.qml.CheckUpdatesFinished() + + if err := f.checkUpdates(); err != nil { + f.log.WithError(err).Error("An error occurred while checking updates") + if isRequestFromUser { + f.qml.UpdateManualError() + } + return + } + + if !f.updater.IsUpdateApplicable(f.newVersionInfo) { + f.log.Debug("No need to update") + if isRequestFromUser { + f.qml.UpdateIsLatestVersion() + } + return + } + + if !f.updater.CanInstall(f.newVersionInfo) { + f.log.Debug("A manual update is required") + f.qml.UpdateManualReady(f.newVersionInfo.Version.String()) + return + } +} + +func (f *FrontendQt) updateForce() { + checkingUpdates.Lock() + defer checkingUpdates.Lock() + + version := "" + if err := f.checkUpdates(); err == nil { + version = f.newVersionInfo.Version.String() + } + + f.qml.UpdateForce(version) +} + +func (f *FrontendQt) setIsAutomaticUpdateOn() { + f.qml.SetIsAutomaticUpdateOn(f.settings.GetBool(settings.AutoUpdateKey)) +} + +func (f *FrontendQt) toggleAutomaticUpdate(makeItEnabled bool) { + f.qml.SetIsAutomaticUpdateOn(makeItEnabled) + isEnabled := f.settings.GetBool(settings.AutoUpdateKey) + if makeItEnabled == isEnabled { + return + } + + f.settings.SetBool(settings.AutoUpdateKey, makeItEnabled) + + f.checkUpdatesAndNotify(false) +} + +func (f *FrontendQt) setIsBetaEnabled() { + channel := f.bridge.GetUpdateChannel() + f.qml.SetIsBetaEnabled(channel == updater.EarlyChannel) +} + +func (f *FrontendQt) toggleBeta(makeItEnabled bool) { + channel := f.bridge.GetUpdateChannel() + + if makeItEnabled == (channel == updater.EarlyChannel) { + f.qml.SetIsBetaEnabled(makeItEnabled) + return + } + + channel = updater.StableChannel + if makeItEnabled { + channel = updater.EarlyChannel + } + + needRestart, err := f.bridge.SetUpdateChannel(channel) + f.setIsBetaEnabled() + + if err != nil { + f.log.WithError(err).Warn("Switching udpate channel failed.") + f.qml.UpdateManualError() + return + } + + if needRestart { + f.restart() + return + } + + f.checkUpdatesAndNotify(false) +} diff --git a/internal/frontend/qt/frontend_users.go b/internal/frontend/qt/frontend_users.go new file mode 100644 index 00000000..f26bd298 --- /dev/null +++ b/internal/frontend/qt/frontend_users.go @@ -0,0 +1,224 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "context" + "encoding/base64" + "github.com/ProtonMail/proton-bridge/internal/frontend/types" + "github.com/ProtonMail/proton-bridge/pkg/pmapi" +) + +func (f *FrontendQt) loadUsers() { + f.usersMtx.Lock() + defer f.usersMtx.Unlock() + + f.qml.Users().clear() + + for _, user := range f.bridge.GetUsers() { + f.qml.Users().addUser(newQMLUserFromBacked(f, user)) + } + + // If there are no active accounts. + if f.qml.Users().Count() == 0 { + f.log.Info("No active accounts") + } +} + +func (f *FrontendQt) userChanged(userID string) { + f.usersMtx.Lock() + defer f.usersMtx.Unlock() + + fUsers := f.qml.Users() + + index := fUsers.indexByID(userID) + user, err := f.bridge.GetUser(userID) + + if user == nil || err != nil { + if index >= 0 { // delete existing user + fUsers.removeUser(index) + } + return + } + + if index < 0 { // add non-existing user + fUsers.addUser(newQMLUserFromBacked(f, user)) + return + } + + // update exiting user + fUsers.users[index].update(user) +} + +func newQMLUserFromBacked(f *FrontendQt, user types.User) *QMLUser { + qu := NewQMLUser(nil) + qu.ID = user.ID() + + qu.update(user) + + qu.ConnectToggleSplitMode(func(activateSplitMode bool) { + go func() { + defer qu.ToggleSplitModeFinished() + if activateSplitMode == user.IsCombinedAddressMode() { + user.SwitchAddressMode() + } + qu.SetSplitMode(!user.IsCombinedAddressMode()) + }() + }) + + qu.ConnectLogout(func() { + qu.SetLoggedIn(false) + go user.Logout() + }) + + qu.ConnectConfigureAppleMail(func(address string) { + go f.configureAppleMail(qu.ID, address) + }) + + return qu +} + +func (f *FrontendQt) login(username, password string) { + var err error + f.password, err = base64.StdEncoding.DecodeString(password) + if err != nil { + f.log.WithError(err).Error("Cannot decode password") + f.qml.LoginUsernamePasswordError("Cannot decode password") + f.loginClean() + return + } + + f.authClient, f.auth, err = f.bridge.Login(username, f.password) + if err != nil { + f.qml.LoginUsernamePasswordError(err.Error()) + f.loginClean() + return + } + + if f.auth.HasTwoFactor() { + f.qml.Login2FARequested() + return + } + if f.auth.HasMailboxPassword() { + f.qml.Login2PasswordRequested() + return + } + + f.finishLogin() +} + +func (f *FrontendQt) login2FA(username, code string) { + if f.auth == nil || f.authClient == nil { + f.log.Errorf("Login 2FA: authethication incomplete %p %p", f.auth, f.authClient) + f.qml.Login2FAErrorAbort("Missing authentication, try again.") + f.loginClean() + return + } + + twoFA, err := base64.StdEncoding.DecodeString(code) + if err != nil { + f.log.WithError(err).Error("Cannot decode 2fa code") + f.qml.LoginUsernamePasswordError("Cannot decode 2fa code") + f.loginClean() + return + } + + err = f.authClient.Auth2FA(context.Background(), string(twoFA)) + if err == pmapi.ErrBad2FACodeTryAgain { + f.log.Warn("Login 2FA: retry 2fa") + f.qml.Login2FAError("") + return + } + + if err == pmapi.ErrBad2FACode { + f.log.Warn("Login 2FA: abort 2fa") + f.qml.Login2FAErrorAbort("") + f.loginClean() + return + } + + if err != nil { + f.log.WithError(err).Warn("Login 2FA: failed.") + f.qml.Login2FAErrorAbort(err.Error()) + f.loginClean() + return + } + + if f.auth.HasMailboxPassword() { + f.qml.Login2PasswordRequested() + return + } + + f.finishLogin() +} + +func (f *FrontendQt) login2Password(username, mboxPassword string) { + var err error + f.password, err = base64.StdEncoding.DecodeString(mboxPassword) + if err != nil { + f.log.WithError(err).Error("Cannot decode mbox password") + f.qml.LoginUsernamePasswordError("Cannot decode mbox password") + f.loginClean() + return + } + + f.finishLogin() +} + +func (f *FrontendQt) finishLogin() { + defer f.loginClean() + + if f.auth == nil || f.authClient == nil { + f.log.Errorf("Finish login: Authethication incomplete %p %p", f.auth, f.authClient) + f.qml.Login2PasswordErrorAbort("Missing authentication, try again.") + return + } + + user, err := f.bridge.FinishLogin(f.authClient, f.auth, f.password) + if err != nil { + f.log.Errorf("Authethication incomplete %p %p", f.auth, f.authClient) + f.qml.Login2PasswordErrorAbort("Missing authentication, try again.") + return + } + + index := f.qml.Users().indexByID(user.ID()) + if index < 0 { + qu := newQMLUserFromBacked(f, user) + qu.SetSetupGuideSeen(false) + f.qml.Users().addUser(qu) + return + } + + f.qml.Users().users[index].update(user) + f.qml.LoginFinished() +} + +func (f *FrontendQt) loginAbort(username string) { + f.loginClean() +} + +func (f *FrontendQt) loginClean() { + f.auth = nil + f.authClient = nil + for i := range f.password { + f.password[i] = '\x00' + } + f.password = f.password[0:0] +} diff --git a/internal/frontend/qt/helpers.go b/internal/frontend/qt/helpers.go new file mode 100644 index 00000000..50d83ce7 --- /dev/null +++ b/internal/frontend/qt/helpers.go @@ -0,0 +1,70 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "regexp" + "strings" + + "github.com/therecipe/qt/core" + "github.com/therecipe/qt/gui" +) + +// getCursorPos returns current mouse position to be able to use in QML +func getCursorPos() *core.QPoint { + return gui.QCursor_Pos() +} + +// newQByteArrayFromString is a wrapper for new QByteArray from string. +func newQByteArrayFromString(name string) *core.QByteArray { + return core.NewQByteArray2(name, len(name)) +} + +var ( + reMultiSpaces = regexp.MustCompile(`\s{2,}`) + reStartWithSymbol = regexp.MustCompile(`^[.,/#!$@%^&*;:{}=\-_` + "`" + `~()]`) +) + +// getInitials based on webapp implementation: +// https://github.com/ProtonMail/WebClients/blob/55d96a8b4afaaa4372fc5f1ef34953f2070fd7ec/packages/shared/lib/helpers/string.ts#L145 +func getInitials(fullName string) string { + words := strings.Split( + reMultiSpaces.ReplaceAllString(fullName, " "), + " ", + ) + + n := 0 + for _, word := range words { + if !reStartWithSymbol.MatchString(word) { + words[n] = word + n++ + } + } + + if n == 0 { + return "?" + } + + initials := words[0][0:1] + if n != 1 { + initials += words[n-1][0:1] + } + return strings.ToUpper(initials) +} diff --git a/internal/frontend/qt/log/log.cpp b/internal/frontend/qt/log/log.cpp new file mode 100644 index 00000000..1950b060 --- /dev/null +++ b/internal/frontend/qt/log/log.cpp @@ -0,0 +1,44 @@ +// 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 . + + +// +build build_qt + +#include "log.h" +#include "_cgo_export.h" + +#include +#include +#include +#include +#include + +void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + Q_UNUSED( type ) + Q_UNUSED( context ) + QByteArray localMsg = msg.toUtf8().prepend("WHITESPACE"); + logMsgPacked( + const_cast( (localMsg.constData()) +10 ), + localMsg.size()-10 + ); +} + +void InstallMessageHandler() { + qInstallMessageHandler(messageHandler); +} + diff --git a/internal/frontend/qt/log/log.go b/internal/frontend/qt/log/log.go new file mode 100644 index 00000000..5af48931 --- /dev/null +++ b/internal/frontend/qt/log/log.go @@ -0,0 +1,46 @@ +// 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 . + +// +build build_qt + +// Package log redirects QML logs to logrus +package log + +//#include "log.h" +import "C" + +import ( + "github.com/sirupsen/logrus" + "github.com/therecipe/qt/core" +) + +var logQML = logrus.WithField("pkg", "frontent/qml") + +// InstallMessageHandler is registering logQML as logger for QML calls. +func InstallMessageHandler() { + C.InstallMessageHandler() +} + +//export logMsgPacked +func logMsgPacked(data *C.char, len C.int) { + logQML.Warn(C.GoStringN(data, len)) +} + +// logDummy is here to trigger qtmoc to create cgo instructions +type logDummy struct { + core.QObject +} diff --git a/internal/frontend/qt/log/log.h b/internal/frontend/qt/log/log.h new file mode 100644 index 00000000..777e97af --- /dev/null +++ b/internal/frontend/qt/log/log.h @@ -0,0 +1,36 @@ +// 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 once + +#ifndef LOGRUS_QML_LOG_H +#define LOGRUS_QML_LOG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif // C++ + + void InstallMessageHandler(); + ; + +#ifdef __cplusplus +} +#endif // C++ + +#endif // LOGRUS_QML_LOG_H diff --git a/internal/frontend/qt/qml_backend.go b/internal/frontend/qt/qml_backend.go new file mode 100644 index 00000000..01f9ce32 --- /dev/null +++ b/internal/frontend/qt/qml_backend.go @@ -0,0 +1,203 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "runtime" + + "github.com/ProtonMail/proton-bridge/internal/bridge" + "github.com/ProtonMail/proton-bridge/internal/config/settings" + dockIcon "github.com/ProtonMail/proton-bridge/internal/frontend/qt/dockicon" + "github.com/therecipe/qt/core" +) + +// QMLBackend connects QML frontend with Go backend. +type QMLBackend struct { + core.QObject + + _ func() *core.QPoint `slot:"getCursorPos"` + _ func() `slot:"quit"` + _ func() `slot:"restart"` + + _ bool `property:dockIconVisible` + + _ QMLUserModel `property:"users"` + + // TODO copy stuff from Bridge_test.qml backend object + _ string `property:"goos"` + + _ func(username, password string) `slot:"login"` + _ func(username, code string) `slot:"login2FA"` + _ func(username, password string) `slot:"login2Password"` + _ func(username string) `slot:"loginAbort"` + _ func(errorMsg string) `signal:"loginUsernamePasswordError"` + _ func(errorMsg string) `signal:"loginFreeUserError"` + _ func(errorMsg string) `signal:"loginConnectionError"` + _ func() `signal:"login2FARequested"` + _ func(errorMsg string) `signal:"login2FAError"` + _ func(errorMsg string) `signal:"login2FAErrorAbort"` + _ func() `signal:"login2PasswordRequested"` + _ func(errorMsg string) `signal:"login2PasswordError"` + _ func(errorMsg string) `signal:"login2PasswordErrorAbort"` + _ func() `signal:"loginFinished"` + + _ func() `signal:"internetOff"` + _ func() `signal:"internetOn"` + + _ func(version string) `signal:"updateManualReady"` + _ func() `signal:"updateManualRestartNeeded"` + _ func() `signal:"updateManualError"` + _ func(version string) `signal:"updateForce"` + _ func() `signal:"updateForceError"` + _ func() `signal:"updateSilentRestartNeeded"` + _ func() `signal:"updateSilentError"` + _ func() `signal:"updateIsLatestVersion"` + _ func() `slot:"checkUpdates"` + _ func() `signal:"checkUpdatesFinished"` + + _ bool `property:"isDiskCacheEnabled"` + _ string `property:"diskCachePath"` + _ func() `signal:"cacheUnavailable"` + _ func() `signal:"cacheCantMove"` + _ func() `signal:"cacheLocationChangeSuccess"` + _ func() `signal:"diskFull"` + _ func(enableDiskCache bool, diskCachePath string) `slot:"changeLocalCache"` + _ func() `signal:"changeLocalCacheFinished"` + + _ bool `property:"isAutomaticUpdateOn"` + _ func(makeItActive bool) `slot:"toggleAutomaticUpdate"` + + _ bool `property:"isAutostartOn"` + _ func(makeItActive bool) `slot:"toggleAutostart"` + _ func() `signal:"toggleAutostartFinished"` + + _ bool `property:"isBetaEnabled"` + _ func(makeItActive bool) `slot:"toggleBeta"` + + _ bool `property:"isDoHEnabled"` + _ func(makeItActive bool) `slot:"toggleDoH"` + + _ bool `property:"useSSLforSMTP"` + _ func(makeItActive bool) `slot:"toggleUseSSLforSMTP"` + _ func() `signal:"toggleUseSSLFinished"` + + _ string `property:"hostname"` + _ int `property:"portIMAP"` + _ int `property:"portSMTP"` + _ func(imapPort, smtpPort int) `slot:"changePorts"` + _ func(port int) bool `slot:"isPortFree"` + _ func() `signal:"changePortFinished"` + _ func() `signal:"portIssueIMAP"` + _ func() `signal:"portIssueSMTP"` + + _ func() `slot:"triggerReset"` + _ func() `signal:"resetFinished"` + + _ string `property:"version"` + _ string `property:"logsPath"` + _ string `property:"licensePath"` + _ string `property:"releaseNotesLink"` + _ string `property:"landingPageLink"` + + _ string `property:"currentEmailClient"` + _ func() `slot:"updateCurrentMailClient"` + _ func(description, address, emailClient string, includeLogs bool) `slot:"reportBug"` + _ func() `signal:"reportBugFinished"` + _ func() `signal:"bugReportSendSuccess"` + _ func() `signal:"bugReportSendError"` + + _ []string `property:"availableKeychain"` + _ string `property:"selectedKeychain"` + _ func(keychain string) `slot:"selectKeychain"` + _ func() `signal:"notifyHasNoKeychain"` + + _ func(email string) `signal:noActiveKeyForRecipient` + _ func() `signal:showMainWindow` + + _ func(address string) `signal:addressChanged` + _ func(address string) `signal:addressChangedLogout` + _ func(username string) `signal:userDisconnected` + _ func() `signal:apiCertIssue` +} + +func (q *QMLBackend) setup(f *FrontendQt) { + q.ConnectGetCursorPos(getCursorPos) + q.ConnectQuit(f.quit) + q.ConnectRestart(f.restart) + + q.ConnectIsDockIconVisible(func() bool { + return dockIcon.GetDockIconVisibleState() + }) + q.ConnectSetDockIconVisible(func(visible bool) { + dockIcon.SetDockIconVisibleState(visible) + }) + + q.SetUsers(NewQMLUserModel(nil)) + f.loadUsers() + + q.SetGoos(runtime.GOOS) + + q.ConnectLogin(func(u, p string) { go f.login(u, p) }) + q.ConnectLogin2FA(func(u, p string) { go f.login2FA(u, p) }) + q.ConnectLogin2Password(func(u, p string) { go f.login2Password(u, p) }) + q.ConnectLoginAbort(func(u string) { go f.loginAbort(u) }) + + go f.checkUpdatesAndNotify(false) + q.ConnectCheckUpdates(func() { go f.checkUpdatesAndNotify(true) }) + + f.setIsDiskCacheEnabled() + f.setDiskCachePath() + q.ConnectChangeLocalCache(f.changeLocalCache) + + f.setIsAutomaticUpdateOn() + q.ConnectToggleAutomaticUpdate(func(m bool) { go f.toggleAutomaticUpdate(m) }) + + f.setIsAutostartOn() + q.ConnectToggleAutostart(f.toggleAutostart) + + f.setIsBetaEnabled() + q.ConnectToggleBeta(func(m bool) { go f.toggleBeta(m) }) + + q.SetIsDoHEnabled(f.settings.GetBool(settings.AllowProxyKey)) + q.ConnectToggleDoH(f.toggleDoH) + + q.SetUseSSLforSMTP(f.settings.GetBool(settings.SMTPSSLKey)) + q.ConnectToggleUseSSLforSMTP(f.toggleUseSSLforSMTP) + + q.SetHostname(bridge.Host) + q.SetPortIMAP(f.settings.GetInt(settings.IMAPPortKey)) + q.SetPortSMTP(f.settings.GetInt(settings.SMTPPortKey)) + q.ConnectChangePorts(f.changePorts) + q.ConnectIsPortFree(f.isPortFree) + + q.ConnectTriggerReset(func() { go f.triggerReset() }) + + f.setVersion() + f.setLogsPath() + // release notes link is set by update + f.setLicensePath() + + f.setCurrentEmailClient() + q.ConnectUpdateCurrentMailClient(func() { go f.setCurrentEmailClient() }) + q.ConnectReportBug(func(d, a, e string, i bool) { go f.reportBug(d, a, e, i) }) + + f.setKeychain() + q.ConnectSelectKeychain(func(k string) { go f.selectKeychain(k) }) +} diff --git a/internal/frontend/qt/qml_users.go b/internal/frontend/qt/qml_users.go new file mode 100644 index 00000000..ae15aea8 --- /dev/null +++ b/internal/frontend/qt/qml_users.go @@ -0,0 +1,135 @@ +// 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 . + +// +build build_qt + +package qt + +import ( + "github.com/ProtonMail/proton-bridge/internal/frontend/types" + "github.com/therecipe/qt/core" +) + +// QMLUserModel stores list of of users +type QMLUserModel struct { + core.QAbstractListModel + + _ map[int]*core.QByteArray `property:"roles"` + _ int `property:"count"` + _ func() `constructor:"init"` + _ func(row int) *core.QVariant `slot:"get"` + + users []*QMLUser +} + +func (um *QMLUserModel) init() { + um.SetRoles(map[int]*core.QByteArray{ + int(core.Qt__UserRole + 1): newQByteArrayFromString("object"), + }) + um.ConnectRowCount(um.rowCount) + um.ConnectData(um.data) + um.ConnectGet(um.get) + um.users = []*QMLUser{} + um.setCount() +} + +func (um *QMLUserModel) data(index *core.QModelIndex, property int) *core.QVariant { + if !index.IsValid() { + return core.NewQVariant() + } + return um.get(index.Row()) +} + +func (um *QMLUserModel) get(index int) *core.QVariant { + if index < 0 || index >= um.rowCount(nil) { + return core.NewQVariant() + } + return um.users[index].ToVariant() +} + +func (um *QMLUserModel) rowCount(*core.QModelIndex) int { + return len(um.users) +} + +func (um *QMLUserModel) setCount() { + um.SetCount(len(um.users)) +} + +func (um *QMLUserModel) addUser(user *QMLUser) { + um.BeginInsertRows(core.NewQModelIndex(), um.rowCount(nil), um.rowCount(nil)) + um.users = append(um.users, user) + um.setCount() + um.EndInsertRows() +} + +func (um *QMLUserModel) removeUser(row int) { + um.BeginRemoveRows(core.NewQModelIndex(), row, row) + um.users = append(um.users[:row], um.users[row+1:]...) + um.setCount() + um.EndRemoveRows() +} + +func (um *QMLUserModel) clear() { + um.BeginRemoveRows(core.NewQModelIndex(), 0, um.rowCount(nil)) + um.users = []*QMLUser{} + um.setCount() + um.EndRemoveRows() +} + +func (um *QMLUserModel) indexByID(id string) int { + for i, qu := range um.users { + if id == qu.ID { + return i + } + } + return -1 +} + +// QMLUser holds data, slots and signals and for user. +type QMLUser struct { + core.QObject + + _ string `property:"username"` + _ string `property:"avatarText"` + _ bool `property:"loggedIn"` + _ bool `property:"splitMode"` + _ bool `property:"setupGuideSeen"` + _ float32 `property:"usedBytes"` + _ float32 `property:"totalBytes"` + _ string `property:"password"` + _ []string `property:"addresses"` + + _ func(makeItActive bool) `slot:"toggleSplitMode"` + _ func() `signal:"toggleSplitModeFinished"` + _ func() `slot:"logout"` + _ func(address string) `slot:"configureAppleMail"` + + ID string +} + +func (qu *QMLUser) update(user types.User) { + username := user.Username() + qu.SetAvatarText(getInitials(username)) + qu.SetUsername(username) + qu.SetLoggedIn(user.IsConnected()) + qu.SetSplitMode(!user.IsCombinedAddressMode()) + qu.SetSetupGuideSeen(true) + qu.SetUsedBytes(1.0) // TODO + qu.SetTotalBytes(10000.0) // TODO + qu.SetPassword(user.GetBridgePassword()) + qu.SetAddresses(user.GetAddresses()) +} diff --git a/internal/frontend/share/Bridge.icns b/internal/frontend/share/Bridge.icns new file mode 100644 index 0000000000000000000000000000000000000000..3520a0eb7cafc5ac95cfffa9191de27ed488094a GIT binary patch literal 266570 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
  • #q=( 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 + + + + + + + + + + + + + + + + + diff --git a/internal/users/user.go b/internal/users/user.go index b3f60932..5f9ef246 100644 --- a/internal/users/user.go +++ b/internal/users/user.go @@ -349,6 +349,7 @@ func (u *User) CheckBridgeLogin(password string) error { func (u *User) UpdateUser(ctx context.Context) error { u.lock.Lock() defer u.lock.Unlock() + defer u.listener.Emit(events.UserRefreshEvent, u.userID) _, err := u.client.UpdateUser(ctx) if err != nil { @@ -376,6 +377,7 @@ func (u *User) SwitchAddressMode() error { u.lock.Lock() defer u.lock.Unlock() + defer u.listener.Emit(events.UserRefreshEvent, u.userID) u.CloseAllConnections() @@ -414,7 +416,6 @@ func (u *User) logout() error { if wasConnected { u.listener.Emit(events.LogoutEvent, u.userID) - u.listener.Emit(events.UserRefreshEvent, u.userID) } return err @@ -425,6 +426,7 @@ func (u *User) logout() error { func (u *User) Logout() error { u.lock.Lock() defer u.lock.Unlock() + defer u.listener.Emit(events.UserRefreshEvent, u.userID) u.log.Debug("Logging out user") diff --git a/internal/users/user_credentials_test.go b/internal/users/user_credentials_test.go index df994fed..6c4cb030 100644 --- a/internal/users/user_credentials_test.go +++ b/internal/users/user_credentials_test.go @@ -41,6 +41,7 @@ func TestUpdateUser(t *testing.T) { m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}), m.credentialsStore.EXPECT().UpdateEmails("user", []string{testPMAPIAddress.Email}).Return(testCredentials, nil), + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user"), ) r.NoError(t, user.UpdateUser(context.Background())) @@ -68,6 +69,7 @@ func TestUserSwitchAddressMode(t *testing.T) { m.pmapiClient.EXPECT().CountMessages(gomock.Any(), "").Return([]*pmapi.MessagesCount{}, nil), m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}), m.credentialsStore.EXPECT().SwitchAddressMode("user").Return(testCredentialsSplit, nil), + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user"), ) // Check switch to split mode. @@ -85,6 +87,7 @@ func TestUserSwitchAddressMode(t *testing.T) { m.pmapiClient.EXPECT().CountMessages(gomock.Any(), "").Return([]*pmapi.MessagesCount{}, nil), m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}), m.credentialsStore.EXPECT().SwitchAddressMode("user").Return(testCredentials, nil), + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user"), ) // Check switch to combined mode. @@ -105,6 +108,7 @@ func TestLogoutUser(t *testing.T) { m.pmapiClient.EXPECT().AuthDelete(gomock.Any()).Return(nil), m.credentialsStore.EXPECT().Logout("user").Return(testCredentialsDisconnected, nil), m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me"), + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user"), ) err := user.Logout() @@ -123,6 +127,7 @@ func TestLogoutUserFailsLogout(t *testing.T) { m.credentialsStore.EXPECT().Logout("user").Return(nil, errors.New("logout failed")), m.credentialsStore.EXPECT().Delete("user").Return(nil), m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me"), + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user"), ) err := user.Logout() diff --git a/internal/users/user_new_test.go b/internal/users/user_new_test.go index b3b4045b..215856f8 100644 --- a/internal/users/user_new_test.go +++ b/internal/users/user_new_test.go @@ -52,8 +52,8 @@ func TestNewUserUnlockFails(t *testing.T) { m.pmapiClient.EXPECT().AuthDelete(gomock.Any()).Return(nil), m.credentialsStore.EXPECT().Logout("user").Return(testCredentialsDisconnected, nil), m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me"), - m.eventListener.EXPECT().Emit(events.LogoutEvent, "user"), m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user"), + m.eventListener.EXPECT().Emit(events.LogoutEvent, "user"), ) checkNewUserHasCredentials(m, "failed to unlock user: bad password", testCredentialsDisconnected) diff --git a/internal/users/users.go b/internal/users/users.go index 01056515..b6b21c63 100644 --- a/internal/users/users.go +++ b/internal/users/users.go @@ -351,6 +351,7 @@ func (u *Users) ClearData() error { func (u *Users) DeleteUser(userID string, clearStore bool) error { u.lock.Lock() defer u.lock.Unlock() + defer u.events.Emit(events.UserRefreshEvent, userID) log := log.WithField("user", userID) diff --git a/internal/users/users_clear_test.go b/internal/users/users_clear_test.go index 91800e85..af54fb7d 100644 --- a/internal/users/users_clear_test.go +++ b/internal/users/users_clear_test.go @@ -32,6 +32,9 @@ func TestClearData(t *testing.T) { users := testNewUsersWithUsers(t, m) defer cleanUpUsersData(users) + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "users") + m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me") m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "users@pm.me") m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "anotheruser@pm.me") diff --git a/internal/users/users_delete_test.go b/internal/users/users_delete_test.go index 0aee1052..de9b32cd 100644 --- a/internal/users/users_delete_test.go +++ b/internal/users/users_delete_test.go @@ -38,7 +38,9 @@ func TestDeleteUser(t *testing.T) { m.credentialsStore.EXPECT().Logout("user").Return(testCredentialsDisconnected, nil), m.credentialsStore.EXPECT().Delete("user").Return(nil), ) + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me") + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") err := users.DeleteUser("user", true) r.NoError(t, err) @@ -61,7 +63,9 @@ func TestDeleteUserWithFailingLogout(t *testing.T) { m.credentialsStore.EXPECT().Delete("user").Return(nil), ) + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me") + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") err := users.DeleteUser("user", true) r.NoError(t, err) diff --git a/internal/users/users_new_test.go b/internal/users/users_new_test.go index c00c42b1..1d286bef 100644 --- a/internal/users/users_new_test.go +++ b/internal/users/users_new_test.go @@ -91,6 +91,7 @@ func TestNewUsersWithConnectedUserWithBadToken(t *testing.T) { m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil) m.credentialsStore.EXPECT().Logout("user").Return(testCredentialsDisconnected, nil) + m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") m.eventListener.EXPECT().Emit(events.LogoutEvent, "user") m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user") m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me")