Add dark theme, German translations and UI improvements

- Dark theme settings
- German language translations
- UI component improvements (ComboSetting, SwitchSetting)
- Display settings layout updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-02-08 06:14:53 +01:00
parent b19d96f82c
commit db7ce5ef4a
7 changed files with 162 additions and 75 deletions

View file

@ -58,6 +58,8 @@ void CarddavCore::save() {
auto realm = Utils::appStringToCoreString(mRealm);
auto storeNewFriendsInIt = mStoreNewFriendsInIt;
lInfo() << log().arg("CarddavCore::save() called") << " mUsername=" << mUsername << " mRealm=" << mRealm;
mCarddavModelConnection->invokeToModel([this, displayName, uri, username, password, realm, storeNewFriendsInIt]() {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
mCarddavModel->save(displayName, uri, username, password, realm, storeNewFriendsInIt);

View file

@ -930,46 +930,46 @@
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="68"/>
<source>settings_call_forward_to_voicemail</source>
<translation type="unfinished"></translation>
<translation>Zur Voicemail</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="26"/>
<source>settings_call_forward_address_cannot_be_empty</source>
<translation type="unfinished"></translation>
<translation>Adresse darf nicht leer sein</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="42"/>
<source>settings_call_forward_activate_title</source>
<extracomment>&quot;Forward calls&quot;</extracomment>
<translation type="unfinished"></translation>
<translation>Anrufe weiterleiten</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="44"/>
<source>settings_call_forward_activate_subtitle</source>
<extracomment>&quot;Enable call forwarding to voicemail or sip address&quot;</extracomment>
<translation type="unfinished"></translation>
<translation>Anrufweiterleitung zur Voicemail oder SIP-Adresse aktivieren</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="56"/>
<source>settings_call_forward_destination_choose</source>
<extracomment>Forward to destination</extracomment>
<translation type="unfinished"></translation>
<translation>Weiterleiten an</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="69"/>
<source>settings_call_forward_to_sipaddress</source>
<translation type="unfinished"></translation>
<translation>Zur SIP-Adresse</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="106"/>
<source>settings_call_forward_sipaddress_title</source>
<extracomment>SIP Address</extracomment>
<translation type="unfinished"></translation>
<translation>SIP-Adresse</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/CallForwardSettingsLayout.qml" line="107"/>
<source>settings_call_forward_sipaddress_placeholder</source>
<translation type="unfinished"></translation>
<translation>sip:benutzer@domain.de</translation>
</message>
</context>
<context>
@ -2694,7 +2694,7 @@ Error</extracomment>
<location filename="../../view/Page/Layout/Settings/ChatSettingsLayout.qml" line="21"/>
<source>settings_chat_notifications_title</source>
<extracomment>Notifications</extracomment>
<translation type="unfinished"></translation>
<translation>Benachrichtigungen</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Settings/ChatSettingsLayout.qml" line="32"/>
@ -6027,7 +6027,13 @@ Pour les activer dans un projet commercial, merci de nous contacter.</source>
<location filename="../../view/Page/Form/Settings/SettingsPage.qml" line="17"/>
<source>settings_call_forward</source>
<extracomment>&quot;Transfert d&apos;appel&quot;</extracomment>
<translation type="unfinished"></translation>
<translation>Anrufweiterleitung</translation>
</message>
<message>
<location filename="../../view/Page/Form/Settings/SettingsPage.qml" line="25"/>
<source>settings_user_interface_title</source>
<extracomment>Display settings</extracomment>
<translation>Anzeige</translation>
</message>
<message>
<location filename="../../view/Page/Form/Settings/SettingsPage.qml" line="19"/>
@ -7872,18 +7878,28 @@ Pour les activer dans un projet commercial, merci de nous contacter.</source>
</message>
<message>
<source>settings_display_dark_mode_subtitle</source>
<extracomment>Enable dark mode for the interface</extracomment>
<translation>Dunkelmodus für die Oberfläche aktivieren</translation>
<extracomment>Enable dark mode (or follows system theme like Breeze Dark)</extracomment>
<translation>Dunkelmodus aktivieren (oder System-Theme wie Breeze Dark folgen)</translation>
</message>
<message>
<source>settings_display_system_dark_detected</source>
<extracomment>System dark theme is detected automatically</extracomment>
<translation>System-Dunkelmodus erkannt (z.B. Breeze Dark)</translation>
</message>
<message>
<source>settings_display_system_light_detected</source>
<extracomment>System light theme is detected</extracomment>
<translation>System-Hellmodus erkannt</translation>
</message>
<message>
<source>settings_display_theme_color_title</source>
<extracomment>Theme color</extracomment>
<translation>Farbschema</translation>
<extracomment>Accent color</extracomment>
<translation>Akzentfarbe</translation>
</message>
<message>
<source>settings_display_theme_color_subtitle</source>
<extracomment>Choose the main color theme</extracomment>
<translation>Wählen Sie das Hauptfarbschema</translation>
<extracomment>Choose the accent color for buttons and highlights</extracomment>
<translation>Wählen Sie die Akzentfarbe für Schaltflächen und Hervorhebungen</translation>
</message>
</context>
</TS>

View file

@ -7771,18 +7771,28 @@ To enable them in a commercial project, please contact us.</translation>
</message>
<message>
<source>settings_display_dark_mode_subtitle</source>
<extracomment>Enable dark mode for the interface</extracomment>
<translation>Enable dark mode for the interface</translation>
<extracomment>Enable dark mode (or follows system theme like Breeze Dark)</extracomment>
<translation>Enable dark mode (or follows system theme like Breeze Dark)</translation>
</message>
<message>
<source>settings_display_system_dark_detected</source>
<extracomment>System dark theme is detected automatically</extracomment>
<translation>System dark theme detected (e.g. Breeze Dark)</translation>
</message>
<message>
<source>settings_display_system_light_detected</source>
<extracomment>System light theme is detected</extracomment>
<translation>System light theme detected</translation>
</message>
<message>
<source>settings_display_theme_color_title</source>
<extracomment>Theme color</extracomment>
<translation>Theme color</translation>
<extracomment>Accent color</extracomment>
<translation>Accent color</translation>
</message>
<message>
<source>settings_display_theme_color_subtitle</source>
<extracomment>Choose the main color theme</extracomment>
<translation>Choose the main color theme</translation>
<extracomment>Choose the accent color for buttons and highlights</extracomment>
<translation>Choose the accent color for buttons and highlights</translation>
</message>
</context>
</TS>

View file

@ -4,33 +4,70 @@ import QtQuick.Layouts
import Linphone
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
ComboBox {
RowLayout {
id: mainItem
Layout.preferredHeight: Utils.getSizeWithScreenRatio(49)
property string titleText
property string subTitleText
property string propertyName
property var propertyOwner
property var propertyOwnerGui
property alias entries: mainItem.model
property alias entries: comboBox.model
property alias model: comboBox.model
property alias textRole: comboBox.textRole
property alias flagRole: comboBox.flagRole
property alias currentIndex: comboBox.currentIndex
property alias currentValue: comboBox.currentValue
property alias listView: comboBox.listView
spacing: Utils.getSizeWithScreenRatio(20)
ColumnLayout {
Layout.minimumHeight: Utils.getSizeWithScreenRatio(32)
Layout.fillWidth: true
spacing: Utils.getSizeWithScreenRatio(4)
visible: titleText.length > 0
Text {
text: titleText
font: Typography.p2l
wrapMode: Text.WordWrap
color: DefaultStyle.main2_600
Layout.fillWidth: true
}
Text {
text: subTitleText
font: Typography.p1
wrapMode: Text.WordWrap
visible: subTitleText.length > 0
color: DefaultStyle.main2_600
Layout.fillWidth: true
}
}
ComboBox {
id: comboBox
Layout.alignment: titleText.length > 0 ? (Qt.AlignRight | Qt.AlignVCenter) : Qt.AlignLeft
Layout.preferredHeight: Utils.getSizeWithScreenRatio(49)
Layout.preferredWidth: titleText.length > 0 ? Utils.getSizeWithScreenRatio(200) : undefined
Layout.fillWidth: titleText.length === 0
oneLine: true
currentIndex: Utils.findIndex(model, function (entry) {
if(propertyOwnerGui)
return Utils.equalObject(entry,propertyOwnerGui.core[propertyName])
return Utils.equalObject(entry, propertyOwnerGui.core[mainItem.propertyName])
else
return Utils.equalObject(entry,propertyOwner[propertyName])
return Utils.equalObject(entry, propertyOwner[mainItem.propertyName])
})
onCurrentValueChanged: {
if(propertyOwnerGui) {
binding.when = !Utils.equalObject(currentValue,propertyOwnerGui.core[propertyName])
}else{
binding.when = !Utils.equalObject(currentValue,propertyOwner[propertyName])
binding.when = !Utils.equalObject(currentValue, propertyOwnerGui.core[mainItem.propertyName])
} else {
binding.when = !Utils.equalObject(currentValue, propertyOwner[mainItem.propertyName])
}
}
Binding {
id: binding
target: propertyOwnerGui ? propertyOwnerGui.core : propertyOwner
property: propertyName
value: mainItem.currentValue
property: mainItem.propertyName
value: comboBox.currentValue
when: false
}
}
}

View file

@ -18,6 +18,7 @@ RowLayout {
signal toggled()
ColumnLayout {
Layout.fillWidth: true
Layout.minimumHeight: Utils.getSizeWithScreenRatio(32)
spacing: Utils.getSizeWithScreenRatio(4)
Text {

View file

@ -89,26 +89,39 @@ AbstractSettingsLayout {
Layout.fillWidth: true
//: Dark mode
titleText: qsTr("settings_display_dark_mode_title")
//: Enable dark mode for the interface
//: Enable dark mode (or follows system theme like Breeze Dark)
subTitleText: qsTr("settings_display_dark_mode_subtitle")
propertyName: "darkModeAllowed"
propertyOwner: SettingsCpp
}
Text {
Layout.fillWidth: true
//: System dark theme is detected automatically
text: DefaultStyle.systemDarkMode
? qsTr("settings_display_system_dark_detected")
: qsTr("settings_display_system_light_detected")
color: DefaultStyle.main2_500main
font.pixelSize: Typography.p2.pixelSize
wrapMode: Text.WordWrap
}
ComboSetting {
Layout.fillWidth: true
//: Theme color
//: Accent color
titleText: qsTr("settings_display_theme_color_title")
//: Choose the main color theme
//: Choose the accent color for buttons and highlights
subTitleText: qsTr("settings_display_theme_color_subtitle")
propertyName: "themeMainColor"
propertyOwner: SettingsCpp
model: [
{text: "Orange", value: "orange"},
{text: "Green", value: "green"},
{text: "Blue", value: "blue"},
{text: "Orange", value: "orange"},
{text: "Red", value: "red"},
{text: "Purple", value: "purple"}
{text: "Purple", value: "purple"},
{text: "Pink", value: "pink"},
{text: "Yellow", value: "yellow"}
]
}
}

View file

@ -4,10 +4,15 @@ import Linphone
import SettingsCpp
QtObject {
// Dark mode detection: use setting or auto-detect from system
property bool isDarkMode: SettingsCpp.darkModeAllowed || systemDarkMode
property bool systemDarkMode: Qt.styleHints.colorScheme === Qt.Dark
property var currentTheme: Themes.themes.hasOwnProperty(SettingsCpp.themeMainColor)
? Themes.themes[SettingsCpp.themeMainColor]
: Themes.themes["orange"]
// Main accent colors (from theme)
property var main1_100: currentTheme.main100
property var main1_200: currentTheme.main200
property var main1_300: currentTheme.main300
@ -15,37 +20,40 @@ QtObject {
property var main1_600: currentTheme.main600
property var main1_700: currentTheme.main700
property var main2_0: "#FAFEFF"
property var main2_100: "#EEF6F8"
property var main2_200: "#DFECF2"
property var main2_300: "#C0D1D9"
property var main2_400: "#9AABB5"
property var main2_500_main: "#6C7A87"
property var main2_600: "#4E6074"
property var main2_700: "#364860"
property var main2_800: "#22334D"
property var main2_900: "#2D3648"
// Main UI colors - switch based on dark mode
property var main2_0: isDarkMode ? "#1a1a1a" : "#FAFEFF"
property var main2_100: isDarkMode ? "#252525" : "#EEF6F8"
property var main2_200: isDarkMode ? "#2d2d2d" : "#DFECF2"
property var main2_300: isDarkMode ? "#3d3d3d" : "#C0D1D9"
property var main2_400: isDarkMode ? "#5a5a5a" : "#9AABB5"
property var main2_500_main: isDarkMode ? "#8a8a8a" : "#6C7A87"
property var main2_600: isDarkMode ? "#b0b0b0" : "#4E6074"
property var main2_700: isDarkMode ? "#c8c8c8" : "#364860"
property var main2_800: isDarkMode ? "#e0e0e0" : "#22334D"
property var main2_900: isDarkMode ? "#f0f0f0" : "#2D3648"
property var grey_0: "#FFFFFF"
property var grey_100: "#F9F9F9"
property var grey_200: "#EDEDED"
property var grey_300: "#C9C9C9"
property var grey_400: "#949494"
property var grey_500: "#4E4E4E"
property var grey_600: "#2E3030"
property var grey_850: "#D9D9D9"
property var grey_900: "#070707"
property var grey_1000: "#000000"
// Grey colors - inverted for dark mode
property var grey_0: isDarkMode ? "#1a1a1a" : "#FFFFFF"
property var grey_100: isDarkMode ? "#252525" : "#F9F9F9"
property var grey_200: isDarkMode ? "#333333" : "#EDEDED"
property var grey_300: isDarkMode ? "#4a4a4a" : "#C9C9C9"
property var grey_400: isDarkMode ? "#6b6b6b" : "#949494"
property var grey_500: isDarkMode ? "#b1b1b1" : "#4E4E4E"
property var grey_600: isDarkMode ? "#d1d1d1" : "#2E3030"
property var grey_850: isDarkMode ? "#404040" : "#D9D9D9"
property var grey_900: isDarkMode ? "#f8f8f8" : "#070707"
property var grey_1000: isDarkMode ? "#ffffff" : "#000000"
// Status colors - keep similar but adjust for dark mode visibility
property var warning_600: "#DBB820"
property var warning_700: "#AF9308"
property var danger_500_main: "#DD5F5F"
property var warning_500_main: "#FFDC2E"
property var danger_700: "#9E3548"
property var danger_900: "#723333"
property var danger_900: isDarkMode ? "#ff6666" : "#723333"
property var success_500_main: "#4FAE80"
property var success_700: "#377d71"
property var success_900: "#1E4C53"
property var success_900: isDarkMode ? "#5fd9a8" : "#1E4C53"
property var info_500_main: "#4AA8FF"
property var info_800_main: "#02528D"
@ -67,10 +75,10 @@ QtObject {
property string flagFont: "Noto Color Emoji"
property string defaultFont: "Noto Sans"
property var numericPadPressedButtonColor: "#EEF7F8"
property var numericPadPressedButtonColor: isDarkMode ? "#2a3a3d" : "#EEF7F8"
property var groupCallButtonColor: "#EEF7F8"
property var groupCallButtonColor: isDarkMode ? "#2a3a3d" : "#EEF7F8"
property var placeholders: '#CACACA' // No name in design
property var placeholders: isDarkMode ? '#555555' : '#CACACA'
}