linux.x86.linphone/BUGFIX_DOUBLE_BUTTONS.md
data 3b3bb966d4 Add ringtone selection dropdown and various bugfixes
- Add ComboBox for ringtone selection in Call Settings
- Convert MKV ringtones to WAV format (Linphone only supports WAV)
- Fix ComboSetting to support dialPlan type for international prefix
- Disable account devices feature to prevent API errors
- Disable automatic update check on startup
- Add ringtone fallback to default when custom file not found
- Fix ringtone dropdown to not override setting on initialization

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

9.9 KiB
Executable file

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
    // ...
}

4. ComboSetting unterstützt verschiedene Model-Typen

Problem

Die ComboSetting-Komponente konnte nur mit einem Model-Typ umgehen. Es gibt aber drei verschiedene Typen:

  1. Audio-Geräte: QVariantList mit Objekten {id: "...", display_name: "..."}
  2. Einfache Einträge: QVariantList mit Objekten {text: "...", value: "..."}
  3. Video-Geräte: QStringList mit einfachen Strings

Symptome

  • Audio-Geräte (Lautsprecher, Mikrofon, Klingel) wurden nach Neustart nicht korrekt angezeigt
  • Kamera-Dropdown zeigte keine Gerätenamen an (nur leere Einträge)

Lösung

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

Die currentIndex-Berechnung, onCurrentIndexChanged und Binding.value wurden erweitert, um alle drei Typen zu erkennen und korrekt zu verarbeiten:

currentIndex: Utils.findIndex(model, function (entry) {
    var currentVal = propertyOwnerGui
        ? propertyOwnerGui.core[mainItem.propertyName]
        : propertyOwner[mainItem.propertyName]
    // Handle different entry types
    if (typeof entry === 'string') {
        // QStringList (video devices): compare strings directly
        return entry === currentVal
    } else if (entry.id !== undefined) {
        // Audio devices: compare by id
        return currentVal && entry.id === currentVal.id
    } else if (entry.value !== undefined) {
        // Simple entries (language, color): compare by value
        return entry.value === currentVal
    }
    return false
})

Datei: Linphone/view/Control/Form/Settings/MultimediaSettings.qml

Für die Kamera-ComboBox wurde textRole: "" gesetzt, da QStringList-Models keine Properties haben:

ComboSetting {
    id: videoDevicesCbox
    entries: SettingsCpp.videoDevices
    propertyName: "videoDevice"
    propertyOwner: SettingsCpp
    textRole: ""  // Empty for QStringList models
    // ...
}

Technischer Hintergrund

Model-Typ Beispiel Vergleich Rückgabewert
QStringList "V4L2: /dev/video0" entry === currentVal entry (String)
Audio-Geräte {id: "pulse:0", display_name: "Speaker"} entry.id === currentVal.id entry (Objekt)
Einfache Einträge {text: "English", value: "en"} entry.value === currentVal entry.value (String)

Zusammenfassung der geänderten Dateien

Datei Änderung
ComboSetting.qml Unterstützung für drei Model-Typen (QStringList, Audio-Geräte, einfache Einträge)
MultimediaSettings.qml textRole: "" für Kamera-ComboBox
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