linux.x86.linphone/BUGFIX_DOUBLE_BUTTONS.md
data ae94b325b1 Fix: Multiple UI bugs - settings display, dark mode, double buttons
- ComboSetting: Fix saved values not showing for language/accent color
  - Add valueRole/textRole and fix comparison logic

- TextField: Fix CardDAV username/realm not displaying when saved
  - Re-establish Qt.binding after Windows password workaround

- Dark Mode fixes:
  - ComboBox popup: Add background color for dark mode
  - DisplaySettingsLayout: Fix typo main2_500main -> main2_500_main
  - CallsWindow: Add window background color for dark mode

- Double buttons fix:
  - CallPage: Clear rightPanelStackView on component creation
  - CallHistoryLayout: Remove explicit sizes, add Layout.alignment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 07:19:07 +01:00

7.5 KiB

Bugfix: Doppelte Buttons in der Anrufdetailansicht

Problem

In der Anrufdetailansicht (CallHistoryLayout) wurden die drei Aktionsbuttons "Anrufen", "Nachricht" und "Videoanruf" nach mehrmaligem Wechseln zwischen Tabs doppelt angezeigt. Sowohl die Icons als auch die Labels erschienen zweimal untereinander.

Symptome

  • Buttons erscheinen normal beim ersten Besuch der Anrufe-Seite
  • Nach Navigation zu einem anderen Tab (z.B. Kontakte) und Rückkehr zu Anrufe: noch OK
  • Nach erneutem Wechsel (2-3 mal): Buttons werden doppelt angezeigt
  • Besuch der Einstellungen (als Overlay) und Rückkehr behob das Problem temporär

Betroffene Dateien

  • Linphone/view/Page/Main/Call/CallPage.qml
  • Linphone/view/Control/Container/Call/CallHistoryLayout.qml
  • Linphone/view/Control/Button/LabelButton.qml

Ursachen

1. Nicht bereinigter StackView-Zustand

Die CallPage wird bei Tab-Wechseln durch einen Loader zerstört und neu erstellt. Der rightPanelStackView wurde bei der Neuerstellung nicht bereinigt, was zu Zustandsproblemen führte.

2. Fehlerhafte Größenangaben bei LabelButtons

Die LabelButtons hatten explizite width: 56 und height: 56 Angaben, obwohl der tatsächliche Inhalt (Button 56x56 + Spacing 8 + Text ~20) größer war. Dies führte zu Layout-Inkonsistenzen bei der Neuberechnung.

3. Fehlende Layout-Ausrichtung

Nach Entfernung der expliziten Größen fehlte eine konsistente vertikale Ausrichtung, was zu Verschiebungen des Videoanruf-Buttons führte.

Lösung

CallPage.qml

Component.onCompleted: {
    console.log("[CallPage] Created, rightPanelStackView.depth:", rightPanelStackView.depth)
    // Ensure clean state on creation
    rightPanelStackView.clear()
}

Erklärung: Bei jeder Neuerstellung der CallPage wird der StackView geleert, um einen sauberen Zustand sicherzustellen.

CallHistoryLayout.qml

RowLayout {
    Layout.alignment: Qt.AlignHCenter
    spacing: Utils.getSizeWithScreenRatio(72)
    visible: !mainItem.isConference

    LabelButton {
        Layout.alignment: Qt.AlignTop  // Hinzugefügt
        button.icon.width: Utils.getSizeWithScreenRatio(24)
        button.icon.height: Utils.getSizeWithScreenRatio(24)
        button.icon.source: AppIcons.phone
        label: qsTr("contact_call_action")
        // ... onClick handler
    }
    // Gleiche Änderung für alle drei LabelButtons
}

Änderungen:

  • Entfernt: width: Utils.getSizeWithScreenRatio(56) und height: Utils.getSizeWithScreenRatio(56) von allen LabelButtons
  • Entfernt: Layout.fillWidth: true und Layout.preferredHeight: childrenRect.height vom RowLayout
  • Hinzugefügt: Layout.alignment: Qt.AlignTop für konsistente vertikale Ausrichtung

Technischer Hintergrund

Navigation und Loader-Verhalten

Die CallPage befindet sich in einem Loader mit active: mainStackLayout.currentIndex === 0. Bei Tab-Wechseln:

  1. currentIndex ändert sich
  2. Loader wird inaktiv → CallPage wird zerstört
  3. Bei Rückkehr wird Loader aktiv → Neue CallPage wird erstellt

Im Gegensatz dazu öffnen die Einstellungen als Overlay (contextual menu), ohne die CallPage zu zerstören.

StackView-Verhalten

Der rightPanelStackView verwendet replace() für Übergänge. Bei schneller Neuerstellung und property-Änderungen (durch onSelectedRowHistoryGuiChanged) konnte es zu Race-Conditions kommen, die zu doppelten Einträgen führten.

Test-Szenario

  1. App starten
  2. Zu "Anrufe" navigieren
  3. Einen Anruf in der Liste anklicken (Details werden rechts angezeigt)
  4. Zu "Kontakte" wechseln
  5. Zurück zu "Anrufe" wechseln
  6. Schritte 4-5 mehrmals wiederholen
  7. Erwartetes Ergebnis: Buttons bleiben korrekt (nicht doppelt, korrekt ausgerichtet)

Datum

2026-02-08


Weitere Bugfixes (2026-02-08)

1. ComboSetting zeigt gespeicherte Werte nicht an

Problem

Die Dropdown-Menüs für Sprache und Akzentfarbe in den Anzeigeeinstellungen zeigten den gespeicherten Wert nicht an. Das erste Element wurde immer angezeigt, auch wenn ein anderer Wert gespeichert war.

Ursache

Die currentIndex-Berechnung verglich das gesamte Model-Entry-Objekt (z.B. {text: "English", value: "en"}) mit dem gespeicherten String-Wert ("en") mit Utils.equalObject(). Dies ergab immer false, da die Typen nicht übereinstimmen.

Lösung

Datei: Linphone/view/Control/Button/Settings/ComboSetting.qml

ComboBox {
    id: comboBox
    // ...
    valueRole: "value"
    textRole: "text"
    currentIndex: Utils.findIndex(model, function (entry) {
        var currentVal = propertyOwnerGui
            ? propertyOwnerGui.core[mainItem.propertyName]
            : propertyOwner[mainItem.propertyName]
        // Compare entry.value with the stored value (both are simple strings)
        return entry.value === currentVal
    })
    onCurrentValueChanged: {
        var storedVal = propertyOwnerGui
            ? propertyOwnerGui.core[mainItem.propertyName]
            : propertyOwner[mainItem.propertyName]
        // currentValue is now just the value string
        binding.when = currentValue !== storedVal
    }

2. CardDAV Benutzername und Realm werden nicht angezeigt

Problem

In den CardDAV-Einstellungen wurden gespeicherte Werte für Benutzername und Realm nicht in den Textfeldern angezeigt.

Ursache

Das TextField.qml hat einen Windows-Workaround im Component.onCompleted:

Component.onCompleted: {
    text = "workaround"
    resetText()
}

Die imperative Zuweisung text = "workaround" bricht den deklarativen Binding zu initialText. Wenn der Core-Wert erst nach der Komponentenerstellung verfügbar ist, wird er nicht angezeigt.

Lösung

Datei: Linphone/view/Control/Input/TextField.qml

Component.onCompleted: {
    text = "workaround"
    // Re-establish binding to initialText after workaround
    text = Qt.binding(function() { return initialText })
}

3. Dark Mode Probleme

3a. ComboBox-Popup ist weiß im Dark Mode

Problem: Das Dropdown-Popup der ComboBox hatte einen weißen Hintergrund im Dark Mode.

Ursache: Das Rectangle im Popup-Hintergrund hatte keine color-Eigenschaft.

Lösung: Datei: Linphone/view/Control/Button/ComboBox.qml

background: Item {
    // ...
    Rectangle {
        id: cboxBg
        anchors.fill: parent
        radius: Utils.getSizeWithScreenRatio(15)
        color: DefaultStyle.grey_100  // Hinzugefügt - passt sich Dark Mode an
    }

3b. Beschreibungstext schwarz im Dark Mode

Problem: Hinweistexte in den Anzeigeeinstellungen waren schwarz und kaum lesbar im Dark Mode.

Ursache: Tippfehler: main2_500main statt main2_500_main

Lösung: Datei: Linphone/view/Page/Layout/Settings/DisplaySettingsLayout.qml

color: DefaultStyle.main2_500_main  // Korrigiert von main2_500main

3c. Anruffenster hell im Dark Mode

Problem: Das Anruffenster hatte einen weißen Hintergrund im Dark Mode.

Ursache: Die color-Eigenschaft wurde nicht gesetzt (fehlt im Gegensatz zu MainWindow.qml).

Lösung: Datei: Linphone/view/Page/Window/Call/CallsWindow.qml

AbstractWindow {
    id: mainWindow
    flags: Qt.Window
    color: DefaultStyle.grey_0  // Hinzugefügt
    // ...
}

Zusammenfassung der geänderten Dateien

Datei Änderung
ComboSetting.qml valueRole/textRole und korrekter Wertvergleich
TextField.qml Binding nach Windows-Workaround wiederherstellen
ComboBox.qml Popup-Hintergrundfarbe für Dark Mode
DisplaySettingsLayout.qml Tippfehler bei Farbname korrigiert
CallsWindow.qml Window-Hintergrundfarbe für Dark Mode