Android Bugfixxing Part 1
the build was successful Details

- Icons Now Show
- Zoom Slider doesn't Crash (2 causes)
 - One desktop/android crash caused by Ellipsis Label (now replaced)
 - One android crash caused by ButtonTextField (fixed)
- Removed some emoji handling that was unused.
This commit is contained in:
Sarah Jamie Lewis 2020-11-20 11:06:41 -08:00
parent cb932d3ca3
commit a5c96964e8
25 changed files with 249 additions and 192 deletions

82
ANDROID_DEBUGGING.md Normal file
View File

@ -0,0 +1,82 @@
# Notes on Android Debugging
If you are reading this you are probably interested in developing Cwtch for Android! Awesome.
The Cwtch UI app is intended to be a single codebase that runs on multiple platforms. This
complicates the build process in favour of simplifying the code (so goes the theory).
We make use of https://github.com/therecipe/qt/ for deploying Go/Qt code to Android. Before you venture into the weeds
of this README please take a look at the [Installation](https://github.com/therecipe/qt/wiki/Installation)
and [Setup instructions](https://github.com/therecipe/qt/wiki/Deploying-Linux-to-Android) in therecipe/qt.
## Building
Check out and follow the instructions at https://github.com/therecipe/qt/wiki/Deploying-Linux-to-Android as they are sufficient,
below you will find high-level notes regarding the process.
You need to run `qtsetup --qt_version=<vesion> full android` for the non-docker setup. You will need to do this
for every major version change of therecipe dependencies.
You will also need the Android 28 SDK (Pie), the NDK, SDK build tools and platform tools, gradle and **JDK 8**
JAVA_HOME=/path/to/jre8
ANDROID_NDK_DIR=/path/to/ndk
Once all that setup is done you should be able to run:
qtdeploy build android
2-4 minutes later an android apk will pop out in `./deploy/android/build-debug.apk`.
### Build Setup Issues we have seen
* `Could not determine java version from <blah>` - this is thrown by gradle inside the `androiddeployqt` process when the
Java version is *not* JRE8. Ensure that JAVA_HOME is pointed to the correct java installation.
* ` readelf <blah> "is not an ordinary file"` - this isn't actually an error that will stop the build, but sometimes
because of the very long debug log output you will come across it when trying to find the *actual* error (which is
probably a Java version issue). It can be safely ignored.
* `could not find QAndroid...` / `CPP build errors` - you will need to run `qtsetup` full android` for the Qt version
you are using.
* Example: androidextras_android.cpp:9:10: fatal error: 'QAndroidActivityResultReceiver' file not found
## Testing on a Real Device
Consult the Android documentation on setting up your device for development.
You will need an android sdk, setup your device for USB Debugging and then with `adb` you can do:
adb install -r ./deploy/android/build-debug.apk
To get the logs you can run
adb logcat
Android Studio provides a nice logcat interface for quickly filtering log files that can be very useful when trying to
debug complex behavior, but command line tools like `grep` and the built-in [logcat filtering](https://developer.android.com/studio/command-line/logcat)
should also suffice.
*Important*: Cwtch UI technically runs *3* different applications: Cwtch Frontend (application client),
Cwtch Backend (application server) and Tor. When filtering logcat you should be aware that some of your messages might
be getting logged by a different process.
(*Ctrl-F Helper: "Why are log messages missing"*)
# Bundled Libraries
There seems to be a bug in Qt (https://bugreports.qt.io/browse/QTBUG-84371) that prevents the use of
`AndroidExtras` in `ANDROID_MODULES_INCLUDE` so we bundle it in `android/libQt5AndroidExtras.so` along with
`libtor` for Tor support.
## Non-SDK Interfaces
e.g. java.lang.NoSuchFieldException: No field mPivotX in class Landroid/graphics/drawable/RotateDrawable$RotateState;
* https://bugreports.qt.io/browse/QTBUG-71590
## Plugins
Theoretically speaking it should be possible to use `ANDROID_EXTRA_PLUGINS` to include support for e.g.
SVG images on Android. However, we have been unable to make it work. If you would like to try, the following
issues might be helpful:
* https://bugreports.qt.io/browse/QTBUG-60022

View File

@ -1,6 +1,9 @@
.PHONY: all clean linux windows android .PHONY: all clean linux windows android
all: clean linux windows android all: clean linux windows android
default: linux default: linux
SHELL := env QT_BUILD_VERSION=$(QT_BUILD_VERSION) $(SHELL)
QT_BUILD_VERSION ?= "5.13.4"
clean: clean:
rm -r vendor || true rm -r vendor || true
@ -18,7 +21,7 @@ android:
linux_build: linux_build:
date date
qtdeploy -qt_version "5.13.0" build linux 2>&1 | tee qtdeploy.log | pv qtdeploy -qt_version $(QT_BUILD_VERSION) build linux 2>&1 | tee qtdeploy.log | pv
date date
cp -R assets deploy/linux/ cp -R assets deploy/linux/
$(MAKE) linux_clean $(MAKE) linux_clean
@ -28,7 +31,7 @@ linux_clean:
windows_build: windows_build:
date date
qtdeploy -qt_version "5.13.0" build windows 2>&1 | tee qtdeploy.log | pv qtdeploy -qt_version $(QT_BUILD_VERSION) build windows 2>&1 | tee qtdeploy.log | pv
date date
cp -R assets deploy/windows/ cp -R assets deploy/windows/
$(MAKE) linux_clean $(MAKE) linux_clean
@ -37,11 +40,11 @@ windows_clean:
#ntd #ntd
android_build: android_build:
mv assets android/ cp -R assets android/
date date
qtdeploy -docker build android 2>&1 | tee qtdeploy.log | pv ## TODO have this also include AndroidExtras (see ANDROID_DEBUGGING) for full notes.
env ANDROID_MODULES_INCLUDE="Core,Gui,Svg,QuickWidgets,Xml" qtdeploy -debug -qt_version $(QT_BUILD_VERSION) build android 2>&1 | tee qtdeploy.log | pv
date date
$(MAKE) android_clean
android_clean: android_clean:
mv android/assets assets mv android/assets assets

Binary file not shown.

12
go.sum
View File

@ -49,6 +49,7 @@ github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/b
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
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.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/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/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -77,8 +78,19 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/struCoder/pidusage v0.1.3 h1:pZcSa6asBE38TJtW0Nui6GeCjLTpaT/jAnNP7dUTLSQ= github.com/struCoder/pidusage v0.1.3 h1:pZcSa6asBE38TJtW0Nui6GeCjLTpaT/jAnNP7dUTLSQ=
github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI= github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
github.com/therecipe/env_darwin_amd64_513 v0.0.0-20190626001412-d8e92e8db4d0 h1:Txh3Vvzx49BQg6OwSuYqOGNndpCWPYScIpEgK5BcGpc=
github.com/therecipe/env_darwin_amd64_513 v0.0.0-20190626001412-d8e92e8db4d0/go.mod h1:mdZdqBBs62KM68t1wD7rjG2NumvwuSNLqmMetEAqI14=
github.com/therecipe/env_linux_amd64_513 v0.0.0-20190626000307-e137a3934da6 h1:i0/LROzMqqMuHJ9gPeH2+So1Icle7zSVRqzXR4Z75hw=
github.com/therecipe/env_linux_amd64_513 v0.0.0-20190626000307-e137a3934da6/go.mod h1:Cq/lZrZTuGhRckzJgZFONK4WCE67AssWhHYj82U5FFI=
github.com/therecipe/env_windows_amd64_513 v0.0.0-20190626000028-79ec8bd06fb2 h1:dpqvgFCZRuxwiJhWVwQZSJ8zDaORf+GiUGxxOGzlQtc=
github.com/therecipe/env_windows_amd64_513 v0.0.0-20190626000028-79ec8bd06fb2/go.mod h1:evzb6PHK/MrRdJyhL1kbQXTfbMu4t4JOLl6iz55ywvk=
github.com/therecipe/env_windows_amd64_513/Tools v0.0.0-20190626000028-79ec8bd06fb2 h1:hM5KSUn4YbSvPuXAWJyywohkDocI+hSEsL+Msc9/FDA=
github.com/therecipe/env_windows_amd64_513/Tools v0.0.0-20190626000028-79ec8bd06fb2/go.mod h1:75GdIZ2clS7WUwhRklktkP02ffFz7+tBx8/Ue8eFexU=
github.com/therecipe/qt v0.0.0-20200126204426-5074eb6d8c41 h1:yBVcrpbaQYJBdKT2pxTdlL4hBE/eM4UPcyj9YpyvSok= github.com/therecipe/qt v0.0.0-20200126204426-5074eb6d8c41 h1:yBVcrpbaQYJBdKT2pxTdlL4hBE/eM4UPcyj9YpyvSok=
github.com/therecipe/qt v0.0.0-20200126204426-5074eb6d8c41/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us= github.com/therecipe/qt v0.0.0-20200126204426-5074eb6d8c41/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
github.com/therecipe/qt v0.0.0-20200904063919-c0c124a5770d h1:T+d8FnaLSvM/1BdlDXhW4d5dr2F07bAbB+LpgzMxx+o=
github.com/therecipe/qt v0.0.0-20200904063919-c0c124a5770d/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
github.com/therecipe/qt/internal/binding/files/docs v0.0.0-20191019224306-1097424d656c h1:/VhcwU7WuFEVgDHZ9V8PIYAyYqQ6KNxFUjBMOf2aFZM=
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200126204426-5074eb6d8c41 h1:My9HYsfDI/fJPZGyilw6066buBiZ7pgKRRgAyvKK5lA= github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200126204426-5074eb6d8c41 h1:My9HYsfDI/fJPZGyilw6066buBiZ7pgKRRgAyvKK5lA=
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200126204426-5074eb6d8c41/go.mod h1:7m8PDYDEtEVqfjoUQc2UrFqhG0CDmoVJjRlQxexndFc= github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200126204426-5074eb6d8c41/go.mod h1:7m8PDYDEtEVqfjoUQc2UrFqhG0CDmoVJjRlQxexndFc=
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426-5074eb6d8c41 h1:jTzKrQ6EIPvKw1B9/wwoKJLrXF+ManMsXoUzufxAdsg= github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426-5074eb6d8c41 h1:jTzKrQ6EIPvKw1B9/wwoKJLrXF+ManMsXoUzufxAdsg=

View File

@ -690,12 +690,6 @@ func (this *GrandCentralDispatcher) setLocaleHelper(locale string) {
} }
func (this *GrandCentralDispatcher) themeScaleChanged(newThemeScale float32) { func (this *GrandCentralDispatcher) themeScaleChanged(newThemeScale float32) {
// TODO: solve why themeScale > 2.0 halts app launch - related task - solve all the qml launch warnings around anchors/layouts
if this.Os() != "android" {
if newThemeScale > 1.99 {
this.SetThemeScale(1.99)
}
}
this.GlobalSettings.Zoom = newThemeScale this.GlobalSettings.Zoom = newThemeScale
WriteGlobalSettings(this.GlobalSettings) WriteGlobalSettings(this.GlobalSettings)
} }

View File

@ -25,7 +25,7 @@ type GlobalSettings struct {
} }
var DefaultGlobalSettings = GlobalSettings{ var DefaultGlobalSettings = GlobalSettings{
Zoom: 1.0, Zoom: 1.9,
Locale: "en", Locale: "en",
Theme: "light", Theme: "light",
PreviousPid: -1, PreviousPid: -1,
@ -68,11 +68,13 @@ func ReadGlobalSettings() *GlobalSettings {
return &settings return &settings
} }
err = json.Unmarshal(settingsBytes, &settings) err = json.Unmarshal(settingsBytes, &settings)
if err != nil { if err != nil {
log.Errorf("Could not parse global ui settings: %v\n", err) log.Errorf("Could not parse global ui settings: %v\n", err)
} }
log.Debugf("MAP: %v", settings.Experiments)
log.Debugf("Settings: %v", settings)
return &settings return &settings
} }

View File

@ -44,6 +44,7 @@ func init() {
} }
func main() { func main() {
if os.Getenv("CWTCH_FOLDER") != "" { if os.Getenv("CWTCH_FOLDER") != "" {
the.CwtchDir = os.Getenv("CWTCH_FOLDER") the.CwtchDir = os.Getenv("CWTCH_FOLDER")
} else if runtime.GOOS == "android" { } else if runtime.GOOS == "android" {
@ -259,6 +260,7 @@ func loadACN() {
} }
} }
// generate a random socks and control port (not real random...these are port numbers...) // generate a random socks and control port (not real random...these are port numbers...)
mrand.Seed(int64(time.Now().Nanosecond())) mrand.Seed(int64(time.Now().Nanosecond()))
port := mrand.Intn(1000) + 9600 port := mrand.Intn(1000) + 9600

View File

@ -75,8 +75,6 @@ ApplicationWindow {
return px * 72 / (Screen.pixelDensity * 25.4) return px * 72 / (Screen.pixelDensity * 25.4)
} }
StackView { StackView {
id: rootStack id: rootStack
@ -115,6 +113,7 @@ ApplicationWindow {
} }
} }
// The actual app // The actual app
property Item mainLayout: Rectangle { property Item mainLayout: Rectangle {
color: Theme.backgroundMainColor color: Theme.backgroundMainColor
@ -191,6 +190,7 @@ ApplicationWindow {
} }
} }
RowLayout { // Profile Pane (contact list + overlays) RowLayout { // Profile Pane (contact list + overlays)
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true

@ -1 +1 @@
Subproject commit b8d01338786625a41ba430ede6430715f5c82b33 Subproject commit 3b9675e25917f667ba4b1cf1db09d44ed328f010

View File

@ -32,7 +32,7 @@ ColumnLayout {
//: ex: "... paste an address here to add a contact ..." //: ex: "... paste an address here to add a contact ..."
placeholderText: qsTr("search-list") placeholderText: qsTr("search-list")
horizontalAlignment: TextInput.AlignHCenter horizontalAlignment: TextInput.AlignHCenter
icon: gcd.assetPath + "core/search-24px.svg" icon: gcd.assetPath + "core/search-24px.webp"
onTextChanged: { onTextChanged: {
@ -47,18 +47,19 @@ ColumnLayout {
Opaque.Icon { Opaque.Icon {
visible:!listpanel.online visible:!listpanel.online
source: gcd.assetPath + "core/negative_heart_24px.svg" source: gcd.assetPath + "core/negative_heart_24px.webp"
iconColor: Theme.mainTextColor iconColor: Theme.mainTextColor
backgroundColor: Theme.backgroundPaneColor backgroundColor: Theme.backgroundPaneColor
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
height: 150 height: 150
width: 150 width: 150
} }
Opaque.EllipsisLabel { Label {
visible:!listpanel.online visible:!listpanel.online
color: Theme.mainTextColor color: Theme.mainTextColor
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
size: 18 * gcd.themeScale elide: Text.ElideRight
font.pixelSize: 18 * gcd.themeScale
text: qsTr("peer-not-online") text: qsTr("peer-not-online")
} }

View File

@ -97,7 +97,7 @@ Opaque.SettingsList { // groupSettingsPane
width: 18 width: 18
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
iconColor: gsp.connected ? Theme.statusbarOnlineFontColor : Theme.statusbarDisconnectedTorFontColor iconColor: gsp.connected ? Theme.statusbarOnlineFontColor : Theme.statusbarDisconnectedTorFontColor
source: gcd.assetPath + (gsp.connected ? "core/signal_cellular_4_bar-24px.svg" : "core/signal_cellular_connected_no_internet_4_bar-24px.svg") source: gcd.assetPath + (gsp.connected ? "core/signal_cellular_4_bar-24px.webp" : "core/signal_cellular_connected_no_internet_4_bar-24px.webp")
} }
} }
RowLayout { RowLayout {
@ -115,7 +115,7 @@ Opaque.SettingsList { // groupSettingsPane
width: 18 width: 18
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
iconColor : gsp.synced ? Theme.statusbarOnlineFontColor : Theme.statusbarConnectingFontColor iconColor : gsp.synced ? Theme.statusbarOnlineFontColor : Theme.statusbarConnectingFontColor
source: gcd.assetPath + (gsp.synced ? "core/syncing-01.svg" : "core/syncing-03.svg") source: gcd.assetPath + (gsp.synced ? "core/syncing-01.webp" : "core/syncing-03.webp")
} }
} }

View File

@ -43,7 +43,7 @@ Opaque.Flickable {
nameLabel.text = "" nameLabel.text = ""
portrait.performTransform = true portrait.performTransform = true
portrait.source = "core/account_circle-24px_negative_space.svg" portrait.source = "core/account_circle-24px_negative_space.webp"
tag = "" tag = ""
confirmDeleteTxt.text = "" confirmDeleteTxt.text = ""
radioUsePassword.checked = true radioUsePassword.checked = true
@ -136,7 +136,7 @@ Opaque.Flickable {
badgeContent: Image {// Profle Type badgeContent: Image {// Profle Type
id: profiletype id: profiletype
source: radioUsePassword.checked ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg" source: radioUsePassword.checked ? gcd.assetPath + "core/lock-24px.webp" : gcd.assetPath + "core/lock-open-24px.webp"
height: 40 * gcd.themeScale height: 40 * gcd.themeScale
width: height width: height
} }

View File

@ -25,7 +25,7 @@ ColumnLayout {
spacing: 20 * gcd.themeScale spacing: 20 * gcd.themeScale
Opaque.ScalingLabel { Opaque.ScalingLabel {
anchors.horizontalCenter: parent.horizontalCenter Layout.alignment: Qt.AlignHCenter
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
size: Theme.primaryTextSize size: Theme.primaryTextSize
@ -56,16 +56,13 @@ ColumnLayout {
Opaque.Button { Opaque.Button {
id: "button" id: "button"
//anchors.horizontalCenter: parent.horizontalCenter
width: 100 * gcd.themeScale width: 100 * gcd.themeScale
height: Theme.primaryTextSize * gcd.themeScale
icon: "lock_open-24px"
//: Unlock //: Unlock
text: qsTr("unlock") text: qsTr("unlock")
height: Theme.primaryTextSize * gcd.themeScale
onClicked: { onClicked: {
gcd.unlockProfiles(txtPassword.text) gcd.unlockProfiles(txtPassword.text)
txtPassword.text = "" txtPassword.text = ""
@ -76,7 +73,7 @@ ColumnLayout {
Opaque.ScalingLabel { Opaque.ScalingLabel {
id: error id: error
anchors.horizontalCenter: parent.horizontalCenter Layout.alignment: Qt.AlignHCenter
color: Theme.textfieldErrorColor color: Theme.textfieldErrorColor
//: 0 profiles loaded with that password //: 0 profiles loaded with that password
text: qsTr("error-0-profiles-loaded-for-password") text: qsTr("error-0-profiles-loaded-for-password")

View File

@ -34,33 +34,40 @@ Opaque.SettingsList { // Add Profile Pane
serverAddEditPane.server_messages = server_messages; serverAddEditPane.server_messages = server_messages;
} }
settings: Column { settings: Column {
anchors.horizontalCenter: parent.horizontalCenter
width: 700
Opaque.ScalingLabel { anchors.horizontalCenter: parent.horizontalCenter
text: server_name width: 700
size: 16
}
Opaque.Setting { Opaque.ScalingLabel {
label: qsTr("server-availability") text: server_name
size: 16
}
Opaque.Setting {
label: qsTr("server-availability")
field: Opaque.ToggleSwitch { field: Opaque.ToggleSwitch {
anchors.right: parent.right anchors.right: parent.right
isToggled: serverAddEditPane.server_available isToggled: serverAddEditPane.server_available
onToggled: function() { onToggled: function() {
serverAddEditPane.server_available = !serverAddEditPane.server_available serverAddEditPane.server_available = !serverAddEditPane.server_available
if (serverAddEditPane.server_available) { if (serverAddEditPane.server_available) {
gcd.startServer(serverAddEditPane.server_name) gcd.startServer(serverAddEditPane.server_name)
} else { } else {
gcd.stopServer(serverAddEditPane.server_name) gcd.stopServer(serverAddEditPane.server_name)
}
} }
} }
} }
}
Opaque.Setting { Opaque.Setting {
label: qsTr("server-autostart") label: qsTr("server-autostart")
@ -87,6 +94,7 @@ Opaque.SettingsList { // Add Profile Pane
} }
} }
Opaque.Setting { Opaque.Setting {
inline: false inline: false
label: qsTr("server-key-bundle") label: qsTr("server-key-bundle")

View File

@ -20,7 +20,7 @@ Opaque.SettingsList { // settingsPane
settings: Column { settings: Column {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 700 width: parent.width - 20
Opaque.Setting { Opaque.Setting {
//: Language //: Language
@ -70,8 +70,7 @@ Opaque.SettingsList { // settingsPane
Opaque.Slider { Opaque.Slider {
id: zoomSlider id: zoomSlider
from: 0.5 from: 0.5
// TODO: find out why > 2.0 halts desktop app on load - task: fix all the qml anchor/layout warnings on load to: 4.0
to: gcd.os == "android" ? 4.0 : 1.9
value: gcd.themeScale value: gcd.themeScale
live: false live: false
snapMode: Slider.SnapAlways snapMode: Slider.SnapAlways
@ -158,8 +157,6 @@ Opaque.SettingsList { // settingsPane
target: gcd target: gcd
onSupplySettings: function(locale, zoom, theme) { onSupplySettings: function(locale, zoom, theme) {
if (zoom != "") zoomSlider.value = zoom
for (var i=0; i < cbLangItems.count; i++) { for (var i=0; i < cbLangItems.count; i++) {
var item = cbLangItems.get(i) var item = cbLangItems.get(i)
if (item["value"] == locale) { if (item["value"] == locale) {

View File

@ -56,7 +56,7 @@ ColumnLayout {
//: ex: "... paste an address here to add a contact ..." //: ex: "... paste an address here to add a contact ..."
//placeholderText: qsTr("paste-address-to-add-contact") //placeholderText: qsTr("paste-address-to-add-contact")
horizontalAlignment: TextInput.AlignHCenter horizontalAlignment: TextInput.AlignHCenter
icon: gcd.assetPath + "core/search-24px.svg" icon: gcd.assetPath + "core/search-24px.webp"
onTextChanged: { onTextChanged: {

View File

@ -76,7 +76,7 @@ Opaque.PortraitRow {
spacing: 16 * gcd.themeScale spacing: 16 * gcd.themeScale
Opaque.Icon { Opaque.Icon {
source: gcd.assetPath + "core/favorite-24px.svg" source: gcd.assetPath + "core/favorite-24px.webp"
iconColor: Theme.toolbarIconColor iconColor: Theme.toolbarIconColor
backgroundColor: rowColor backgroundColor: rowColor
height: 18 * gcd.themeScale height: 18 * gcd.themeScale
@ -86,7 +86,7 @@ Opaque.PortraitRow {
} }
Opaque.Icon { Opaque.Icon {
source: gcd.assetPath + "core/delete-24px.svg" source: gcd.assetPath + "core/delete-24px.webp"
iconColor: Theme.toolbarIconColor iconColor: Theme.toolbarIconColor
backgroundColor: rowColor backgroundColor: rowColor
height: 18 * gcd.themeScale height: 18 * gcd.themeScale

View File

@ -109,25 +109,23 @@ Rectangle {
color: parent.color color: parent.color
} }
Opaque.EllipsisLabel { Label {
id: handle id: handle
visible: !fromMe && !calendarEvent visible: !fromMe && !calendarEvent
text: displayName text: displayName
color: Theme.messageFromOtherTextColor color: Theme.messageFromOtherTextColor
size: Theme.chatSize * gcd.themeScale
weight: Font.Bold elide: Text.ElideRight
font.pixelSize: Theme.chatSize * gcd.themeScale
font.weight: Font.Bold
font.family: Fonts.applicationFontBold.name font.family: Fonts.applicationFontBold.name
font.styleName: "Bold" font.styleName: "Bold"
leftPadding: 10 * gcd.themeScale leftPadding: 10 * gcd.themeScale
topPadding: 10 * gcd.themeScale topPadding: 10 * gcd.themeScale
container: lbl
} }
onWidthChanged: { handle.textResize() }
Column { Column {
id: colMessageBubble id: colMessageBubble
@ -176,7 +174,7 @@ Rectangle {
Image { // ACKNOWLEDGEMENT ICON Image { // ACKNOWLEDGEMENT ICON
id: ack id: ack
source: root.error != "" ? gcd.assetPath + "fontawesome/regular/window-close.svg" : (root.ackd ? gcd.assetPath + "fontawesome/regular/check-circle.svg" : gcd.assetPath + "fontawesome/regular/hourglass.svg") source: root.error != "" ? gcd.assetPath + "core/fontawesome/regular/window-close.webp" : (root.ackd ? gcd.assetPath + "core/fontawesome/regular/check-circle.svg" : gcd.assetPath + "core/fontawesome/regular/hourglass.svg")
height: Theme.chatMetaTextSize * gcd.themeScale height: Theme.chatMetaTextSize * gcd.themeScale
width: Theme.chatMetaTextSize * gcd.themeScale width: Theme.chatMetaTextSize * gcd.themeScale
anchors.bottom: parent.bottom anchors.bottom: parent.bottom

View File

@ -111,7 +111,7 @@ ColumnLayout {
text: "" text: ""
padding: 6 * gcd.themeScale padding: 6 * gcd.themeScale
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
textFormat: Text.RichText textFormat: Text.PlainText
width: rectMessage.width width: rectMessage.width
color: Theme.mainTextColor color: Theme.mainTextColor
@ -208,7 +208,7 @@ ColumnLayout {
Opaque.Icon { // SEND MESSAGE BUTTON Opaque.Icon { // SEND MESSAGE BUTTON
id: btnSend id: btnSend
source: gcd.assetPath + "core/send-24px.svg" source: gcd.assetPath + "core/send-24px.webp"
width: colRight.width width: colRight.width
height: 50 * gcd.themeScale height: 50 * gcd.themeScale
size: 36 * gcd.themeScale size: 36 * gcd.themeScale
@ -219,24 +219,10 @@ ColumnLayout {
property int nextMessageID: 1 property int nextMessageID: 1
TextEdit {
id: txtHidden
visible: false
textFormat: Text.RichText
}
onClicked: { onClicked: {
// Cannot use .text b/c in rich text mode it is always full of html var txt = txtMessage.text.trim()
if (txtMessage.length != 0) { if (txt.length > 0) {
txtHidden.text = restoreEmoji(txtMessage.text) root.sendClicked(txt)
txtHidden.text = txtHidden.text.replace(/<br \/>/g,"[:newline:]");
var txt = txtHidden.text.trim()
if (txt.length > 0) {
var rawText = txtHidden.getText(0, txtHidden.text.length)
root.sendClicked(rawText)
}
} }
txtMessage.text = "" txtMessage.text = ""
} }
@ -248,7 +234,7 @@ ColumnLayout {
Opaque.Icon { // EMOJI DRAWER BUTTON Opaque.Icon { // EMOJI DRAWER BUTTON
id: btnEmoji id: btnEmoji
source: gcd.assetPath + "core/mood-24px.svg" source: gcd.assetPath + "core/mood-24px.webp"
size: 25 size: 25
height: 36 * gcd.themeScale height: 36 * gcd.themeScale
@ -263,7 +249,7 @@ ColumnLayout {
Opaque.Icon { Opaque.Icon {
id: btnAttach id: btnAttach
source: gcd.assetPath + "core/attach_file-24px.svg" source: gcd.assetPath + "core/attach_file-24px.webp"
size: 25 size: 25
height: 36 * gcd.themeScale height: 36 * gcd.themeScale

View File

@ -31,6 +31,7 @@ Item {
onDualPaneChanged: { realignProfile() } onDualPaneChanged: { realignProfile() }
function realignProfile() { function realignProfile() {
if (dualPane) { if (dualPane) {
profile.height = Theme.contactPortraitSize * logscale profile.height = Theme.contactPortraitSize * logscale
@ -89,7 +90,7 @@ Item {
badgeContent: Image {// Profle Type badgeContent: Image {// Profle Type
id: profiletype id: profiletype
source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg" source: tag == "v1-userPassword" ? gcd.assetPath + "core/lock-24px.webp" : gcd.assetPath + "core/lock_open-24px.webp"
height: Theme.badgeTextSize * gcd.themeScale height: Theme.badgeTextSize * gcd.themeScale
width: height width: height
} }
@ -105,17 +106,16 @@ Item {
id: nameCenter id: nameCenter
width: name.width + addBtn.width width: name.width + addBtn.width
Opaque.EllipsisLabel { Label {
id: name id: name
color: Theme.portraitOnlineTextColor color: Theme.portraitOnlineTextColor
size: Theme.usernameSize * gcd.themeScale elide: Text.ElideRight
weight: Font.Bold font.pixelSize: Theme.usernameSize * gcd.themeScale
font.weight: Font.Bold
font.family: Fonts.applicationFontExtraBold.name font.family: Fonts.applicationFontExtraBold.name
font.styleName: "ExtraBold" font.styleName: "ExtraBold"
text: nick text: nick
extraPadding: addBtn.width + 30
container: nameRow
} }
Opaque.Button { // Add Button Opaque.Button { // Add Button
@ -124,7 +124,7 @@ Item {
anchors.left: name.right anchors.left: name.right
anchors.top: name.top anchors.top: name.top
icon: "solid/plus" icon: "fontawesome/solid/plus"
height: name.height height: name.height
width: height width: height

View File

@ -93,6 +93,17 @@ ColumnLayout {
image: _image image: _image
tag: _tag tag: _tag
Layout.fillWidth: true Layout.fillWidth: true
rowClicked: function(handle) {
gcd.broadcast("ResetMessagePane");
gcd.broadcast("ResetProfile");
gcd.selectedProfile = handle;
gcd.loadProfile(handle);
parentStack.pane = parentStack.profilePane;
}
editClicked: function(handle, displayName, tag, image) {
profileAddEditPane.load(handle, displayName, tag, image);
parentStack.pane = parentStack.addEditProfilePane;
}
} }
} }
@ -101,7 +112,7 @@ ColumnLayout {
handle: "" handle: ""
displayName: qsTr("add-new-profile-btn") displayName: qsTr("add-new-profile-btn")
nameColor: Theme.mainTextColor nameColor: Theme.mainTextColor
image: "/core/account_circle-24px_negative_space.svg" //"/fontawesome/regular/user.svg" image: "/core/account_circle-24px_negative_space.webp"
tag: "" tag: ""
portraitBorderColor: Theme.defaultButtonColor portraitBorderColor: Theme.defaultButtonColor
portraitColor: Theme.defaultButtonColor portraitColor: Theme.defaultButtonColor
@ -109,7 +120,7 @@ ColumnLayout {
portraitPerformTransform: true portraitPerformTransform: true
badgeVisible: true badgeVisible: true
badgeContent: Image { badgeContent: Image {
source: gcd.assetPath + "/fontawesome/solid/plus.svg" source: gcd.assetPath + "core/fontawesome/solid/plus.webp"
height: Theme.badgeTextSize * gcd.themeScale height: Theme.badgeTextSize * gcd.themeScale
width: height width: height
} }

View File

@ -11,55 +11,53 @@ import "../opaque" as Opaque
import "../opaque/styles" import "../opaque/styles"
import "../opaque/theme" import "../opaque/theme"
Opaque.PortraitRow { RowLayout {
id: root id: root
badgeColor: Theme.portraitProfileBadgeColor property alias handle: prow.handle
property alias displayName: prow.displayName
property alias image: prow.image
property alias tag: prow.tag
property alias badgeColor: prow.badgeColor
property var rowClicked: {}
property var editClicked: {}
portraitBorderColor: Theme.portraitOnlineBorderColor Opaque.PortraitRow {
portraitColor: Theme.portraitOnlineBackgroundColor id: prow
nameColor: Theme.portraitOnlineTextColor badgeColor: Theme.portraitProfileBadgeColor
onionColor: Theme.portraitOnlineTextColor Layout.fillWidth: true
portraitBorderColor: Theme.portraitOnlineBorderColor
portraitColor: Theme.portraitOnlineBackgroundColor
nameColor: Theme.portraitOnlineTextColor
onionColor: Theme.portraitOnlineTextColor
badgeContent: Image {// Profle Type badgeContent: Image {// Profle Type
id: profiletype id: profiletype
source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg" source: tag == "v1-userPassword" ? gcd.assetPath + "core/lock-24px.webp" : gcd.assetPath + "core/lock_open-24px.webp"
height: Theme.badgeTextSize * gcd.themeScale height: Theme.badgeTextSize * gcd.themeScale
width: height width: height
}
onClicked: rowClicked(handle)
} }
Opaque.Icon {// Edit BUTTON Opaque.Icon {// Edit BUTTON
id: btnEdit id: btnEdit
source: gcd.assetPath + "core/edit-24px.svg" source: gcd.assetPath + "core/edit-24px.webp"
Layout.minimumWidth: 80
backgroundColor: root.color Layout.fillHeight: true
backgroundColor: Theme.backgroundMainColor
hilightBackgroundColor: Theme.backgroundHilightElementColor
iconColor: Theme.altTextColor iconColor: Theme.altTextColor
anchors.right: parent.right
//rectUnread.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 1 * gcd.themeScale // Layout.alignment: Qt.AlignVCenter
anchors.rightMargin: 20 * gcd.themeScale
height: parent.height * 0.5
width: parent.height * 0.5
size: parent.height * 0.5
onClicked: { height: root.height / 2
profileAddEditPane.load(handle, displayName, tag, image) width: root.height / 2
parentStack.pane = parentStack.addEditProfilePane size: root.height / 2
}
onHover: function (hover) { onClicked: editClicked(handle, displayName, tag, image)
root.isHover = hover
}
}
onClicked: function openClick(handle) {
gcd.broadcast("ResetMessagePane");
gcd.broadcast("ResetProfile");
gcd.selectedProfile = handle
gcd.loadProfile(handle)
parentStack.pane = parentStack.profilePane
} }
} }

View File

@ -93,6 +93,14 @@ ColumnLayout {
autostart: _autostart autostart: _autostart
messages: _messages messages: _messages
Layout.fillWidth: true Layout.fillWidth: true
rowClicked: function(handle) {
}
editClicked: function(handle, displayName, tag, image) {
gcd.checkServer(handle)
serverAddEditPane.load(handle, displayName, status, _autostart, _messages, _bundle)
parentStack.pane = parentStack.addEditServerPane
}
} }
} }
@ -101,13 +109,13 @@ ColumnLayout {
handle: "" handle: ""
displayName: qsTr("add-new-profile-btn") displayName: qsTr("add-new-profile-btn")
nameColor: Theme.mainTextColor nameColor: Theme.mainTextColor
image: "/fontawesome/regular/user.svg" image: "core/fontawesome/regular/user.webp"
tag: "" tag: ""
portraitBorderColor: Theme.portraitOnlineBorderColor portraitBorderColor: Theme.portraitOnlineBorderColor
portraitColor: Theme.portraitOnlineBackgroundColor portraitColor: Theme.portraitOnlineBackgroundColor
badgeVisible: true badgeVisible: true
badgeContent: Image { badgeContent: Image {
source: gcd.assetPath + "/fontawesome/solid/plus.svg" source: gcd.assetPath + "core/fontawesome/solid/plus.webp"
height: Theme.badgeTextSize * gcd.themeScale height: Theme.badgeTextSize * gcd.themeScale
width: height width: height
} }

View File

@ -11,55 +11,13 @@ import "../opaque" as Opaque
import "../opaque/styles" import "../opaque/styles"
import "../opaque/theme" import "../opaque/theme"
Opaque.PortraitRow { ProfileRow {
id: root id: root
property int status; property int status
property string bundle; property string bundle
property bool autostart; property bool autostart
property int messages; property int messages
portraitBorderColor: Theme.portraitOnlineBorderColor
portraitColor: Theme.portraitOnlineBackgroundColor
nameColor: Theme.portraitOnlineTextColor
onionColor: Theme.portraitOnlineTextColor
badgeColor: status == 1 ? Theme.portraitOnlineBadgeColor : Theme.portraitOfflineBadgeColor badgeColor: status == 1 ? Theme.portraitOnlineBadgeColor : Theme.portraitOfflineBadgeColor
badgeVisible: true // TODO Badge Images
Opaque.Icon {// Edit BUTTON
id: btnEdit
source: gcd.assetPath + "core/edit-24px.svg"
backgroundColor: root.color
iconColor: Theme.altTextColor
anchors.right: parent.right
//rectUnread.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 1 * gcd.themeScale
anchors.rightMargin: 20 * gcd.themeScale
height: parent.height * 0.5
width: parent.height * 0.5
size: parent.height * 0.5
onClicked: {
gcd.checkServer(handle)
serverAddEditPane.load(handle, displayName, status, autostart, messages, bundle)
parentStack.pane = parentStack.addEditServerPane
}
onHover: function (hover) {
root.isHover = hover
gcd.checkServer(handle)
}
}
onClicked: function openClick(handle) {
}
} }

View File

@ -63,9 +63,9 @@ Rectangle {
statusbar.color = Theme.statusbarDisconnectedInternetColor statusbar.color = Theme.statusbarDisconnectedInternetColor
statusMessage.color = Theme.statusbarDisconnectedInternetFontColor statusMessage.color = Theme.statusbarDisconnectedInternetFontColor
networkStatus.iconColor = Theme.statusbarDisconnectedInternetFontColor networkStatus.iconColor = Theme.statusbarDisconnectedInternetFontColor
networkStatus.source = gcd.assetPath + "core/signal_cellular_off-24px.svg" networkStatus.source = gcd.assetPath + "core/signal_cellular_off-24px.webp"
connectionStatus.iconColor = Theme.statusbarDisconnectedInternetFontColor connectionStatus.iconColor = Theme.statusbarDisconnectedInternetFontColor
connectionStatus.source = gcd.assetPath + "core/syncing-03.svg" connectionStatus.source = gcd.assetPath + "core/syncing-03.webp"
//: Disconnected from the internet, check your connection //: Disconnected from the internet, check your connection
statusMessage.text = qsTr("network-status-disconnected") statusMessage.text = qsTr("network-status-disconnected")
show() show()
@ -73,9 +73,9 @@ Rectangle {
statusbar.color = Theme.statusbarDisconnectedTorColor statusbar.color = Theme.statusbarDisconnectedTorColor
statusMessage.color = Theme.statusbarDisconnectedTorFontColor statusMessage.color = Theme.statusbarDisconnectedTorFontColor
networkStatus.iconColor = Theme.statusbarDisconnectedTorFontColor networkStatus.iconColor = Theme.statusbarDisconnectedTorFontColor
networkStatus.source = gcd.assetPath + "core/signal_cellular_connected_no_internet_4_bar-24px.svg" networkStatus.source = gcd.assetPath + "core/signal_cellular_connected_no_internet_4_bar-24px.webp"
connectionStatus.iconColor = Theme.statusbarDisconnectedTorFontColor connectionStatus.iconColor = Theme.statusbarDisconnectedTorFontColor
connectionStatus.source = gcd.assetPath + "core/syncing-03.svg" connectionStatus.source = gcd.assetPath + "core/syncing-03.webp"
//: Attempting to connect to Tor network //: Attempting to connect to Tor network
statusMessage.text = qsTr("network-status-attempting-tor") statusMessage.text = qsTr("network-status-attempting-tor")
show() show()
@ -83,9 +83,9 @@ Rectangle {
statusbar.color = Theme.statusbarConnectingColor statusbar.color = Theme.statusbarConnectingColor
statusMessage.color = Theme.statusbarConnectingFontColor statusMessage.color = Theme.statusbarConnectingFontColor
networkStatus.iconColor = Theme.statusbarConnectingFontColor networkStatus.iconColor = Theme.statusbarConnectingFontColor
networkStatus.source = gcd.assetPath + "core/signal_cellular_connected_no_internet_4_bar-24px.svg" networkStatus.source = gcd.assetPath + "core/signal_cellular_connected_no_internet_4_bar-24px.webp"
connectionStatus.iconColor = Theme.statusbarConnectingFontColor connectionStatus.iconColor = Theme.statusbarConnectingFontColor
connectionStatus.source = gcd.assetPath + "core/syncing-02.svg" connectionStatus.source = gcd.assetPath + "core/syncing-02.webp"
//: Connecting... //: Connecting...
statusMessage.text = qsTr("network-status-connecting") statusMessage.text = qsTr("network-status-connecting")
show() show()
@ -93,9 +93,9 @@ Rectangle {
statusbar.color = Theme.statusbarOnlineColor statusbar.color = Theme.statusbarOnlineColor
statusMessage.color = Theme.statusbarOnlineFontColor statusMessage.color = Theme.statusbarOnlineFontColor
networkStatus.iconColor = Theme.statusbarOnlineFontColor networkStatus.iconColor = Theme.statusbarOnlineFontColor
networkStatus.source = gcd.assetPath + "core/signal_cellular_4_bar-24px.svg" networkStatus.source = gcd.assetPath + "core/signal_cellular_4_bar-24px.webp"
connectionStatus.iconColor = Theme.statusbarOnlineFontColor connectionStatus.iconColor = Theme.statusbarOnlineFontColor
connectionStatus.source = gcd.assetPath + "core/syncing-01.svg" connectionStatus.source = gcd.assetPath + "core/syncing-01.webp"
//: Online //: Online
statusMessage.text = qsTr("network-status-online") statusMessage.text = qsTr("network-status-online")
hide() hide()