diff --git a/src/contactview/assets/welcome.html b/src/contactview/assets/welcome.html
index 858bf0ae..4c836877 100644
--- a/src/contactview/assets/welcome.html
+++ b/src/contactview/assets/welcome.html
@@ -1,24 +1,18 @@
Welcome to Ring-KDE
- Ring-KDE is build entirely using standard compliant technologies. All of
- your data never leave your computer and is readable using various third
- party application. If you wish to keep your account, don't forget to
- export it somewhere safe. If you format your computer without having the
- account on another device, it will be lost forever
+ Above is the search box. To begin to use Ring-KDE, you need to add someone
+ to talk too. Since no contacts have been imported yet, use the following
+ search term to locate someone:
- Below is the search box. To begin to use Ring-KDE, you need to add someone
- to talk too. Since no contacts have been imported yet, use the following
- search term to locate someone:
- Their registered Ring username
- Their unique Ring number identifier
- Their phone number
- Their name
-
diff --git a/src/jamisearch/qml/searchbox.qml b/src/jamisearch/qml/searchbox.qml
index 225bf763..6cf07e4d 100644
--- a/src/jamisearch/qml/searchbox.qml
+++ b/src/jamisearch/qml/searchbox.qml
@@ -1,173 +1,181 @@
/***************************************************************************
* Copyright (C) 2018 by Bluesystems *
* Author : Emmanuel Lepage Vallee *
* *
* This program 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. *
* *
* This program 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 this program. If not, see . *
**************************************************************************/
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.0
import org.kde.kirigami 2.2 as Kirigami
import net.lvindustries.ringqtquick 1.0 as RingQtQuick
Item {
id: searchBox
property bool empty: search.text == ""
property var searchView: null
property real xPadding: 2*Kirigami.Units.largeSpacing +2 /*border*/
property alias searchFocus: search.focus
property alias labelWidth: findLabel.implicitWidth
Kirigami.Theme.colorSet: Kirigami.Theme.View
+ function forceFocus() {
+ search.forceActiveFocus(Qt.OtherFocusReason)
+ }
+
function hide() {
search.text = ""
search.focus = false
if (RingSession.callModel.hasDialingCall)
RingSession.callModel.dialingCall().performAction(RingQtQuick.Call.REFUSE)
}
FontMetrics {
id: textMetric
font: search.font
}
TextField {
id: search
+
+ // Auto complete an auto completion == fail
+ inputMethodHints: Qt.ImhNoPredictiveText
+
width: focus ? searchView.width - xPadding : parent.width
x: focus ? -(searchView.width-searchBox.width ) + xPadding: 0
y: (focus ? searchBox.height : 0) + Kirigami.Units.largeSpacing
leftPadding: Kirigami.Units.largeSpacing + 1 /*border*/
topPadding: Kirigami.Units.largeSpacing
font.pointSize: Kirigami.Theme.defaultFont.pointSize*1.4
text: RingSession.callModel.hasDialingCall ?
RingSession.callModel.dialingCall().dialNumber : ""
Behavior on x {
NumberAnimation {duration: 300}
}
Behavior on y {
NumberAnimation {duration: 150}
}
Behavior on width {
NumberAnimation {duration: 300}
}
background : Item {
height: textMetric.height*1.5
Rectangle {
height: parent.height - 2 // 1px border
width: parent.width
color: "transparent"
border.width: 1
border.color: Kirigami.Theme.textColor
opacity: search.focus ? 0.8 : 0.5
radius: search.text == "" && !search.focus ? 99 : 5
Behavior on opacity {
NumberAnimation {duration: 100}
}
Behavior on radius {
NumberAnimation {duration: 200; easing.type: Easing.OutQuad}
}
RowLayout {
height: parent.height
y: search.text == "" && !search.focus ? 0 : -search.height
x: search.focus ? (searchView.width-searchBox.width)/2 : 0
spacing: 5
Behavior on opacity {
NumberAnimation {duration: 100}
}
Behavior on y {
NumberAnimation {duration: 200}
}
Item {
width: 2
}
Image {
width: parent.height - 6
height: parent.height - 6
Layout.alignment: Qt.AlignVCenter
sourceSize.height: parent.height - 6
sourceSize.width: parent.height - 6
source: "image://SymbolicColorizer/image://icon/file-search-symbolic"
}
Text {
id: findLabel
Layout.fillWidth: true
color: Kirigami.Theme.textColor
text: i18n("Find someone")
Layout.alignment: Qt.AlignVCenter
font.pixelSize: parent.height * 0.55
}
}
}
}
onTextChanged: {
// Cache the text to avoid a binding loop when the dialing call
// is created for the first time
var text = search.text
if (RingSession.callModel.hasDialingCall || text != "") {
var call = RingSession.callModel.dialingCall()
call.dialNumber = text
}
}
Keys.onDownPressed: {
searchView.currentIndex = (searchView.currentIndex == searchView.count - 1) ?
0 : searchView.currentIndex + 1
}
Keys.onUpPressed: {
searchView.currentIndex = (searchView.currentIndex == 0) ?
searchView.count - 1 : searchView.currentIndex - 1
}
Keys.onReturnPressed: {
var cm = searchView.currentItem.contactMethod
// Display an error message when the selected element doesn't exist
if (!searchView.currentItem.isSelectable) {
- displayNotFoundMessage()
+ searchView.displayNotFoundMessage()
return
}
if (!cm)
return
cm = RingSession.individualDirectory.fromTemporary(cm)
mainPage.currentContactMethod = cm
searchBox.hide()
}
Keys.onEscapePressed: {
searchBox.hide()
}
Keys.onPressed: {
if (event.key == Qt.Key_Backspace && search.text == "")
searchBox.hide()
}
}
}
diff --git a/src/jamisearch/qml/searchoverlay.qml b/src/jamisearch/qml/searchoverlay.qml
index cebf3a80..26e51f77 100644
--- a/src/jamisearch/qml/searchoverlay.qml
+++ b/src/jamisearch/qml/searchoverlay.qml
@@ -1,314 +1,285 @@
/***************************************************************************
* Copyright (C) 2018 by Bluesystems *
* Author : Emmanuel Lepage Vallee *
* *
* This program 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. *
* *
* This program 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 this program. If not, see . *
**************************************************************************/
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0 as Layouts
import QtGraphicalEffects 1.0
import org.kde.kirigami 2.0 as Kirigami
import net.lvindustries.ringqtquick 1.0 as RingQtQuick
import org.kde.ringkde.jamisearch 1.0 as JamiSearch
Item {
id: seachOverlay
visible: searchState.activeState || searchState.firstSearchState
// Properties
- property alias topLevel: seachOverlay.parent
property var source: null
- property bool active: searchBox && searchBox.searchFocus
- property alias currentIndex: searchView.currentIndex
- property alias currentItem: searchView.currentItem
+ property bool active: searchState.display
property QtObject searchBox: null
property bool displayWelcome: searchState.firstSearchState
+ property alias currentItem: searchView.currentItem // used be the search box
+
// Signals
signal contactMethodSelected(var cm)
signal displayNotFoundMessage()
// Functions
function hide() {
searchBox.hide()
}
SystemPalette {
id: inactivePalette
colorGroup: SystemPalette.Inactive
}
// The algorithm used to define what's visible. It is in an class because
// the expression size was no longer maintainable.
JamiSearch.State {
id: searchState
- searchEmpty: searchBox.empty
- focussed: active
+ searchEmpty: (!searchBox) || searchBox.empty
+ focussed: searchBox && searchBox.searchFocus
+ onDisplayChanged: {
+ if (display) {
+ searchBox.searchFocus = true
+ searchBox.forceFocus()
+ }
+ }
}
// Track if the user asked to never see some information ever again
JamiSearch.TipModel {
id: displayTips
}
// Add a blurry background
ShaderEffectSource {
id: effectSource
visible: false
sourceItem: seachOverlay.source
anchors.fill: seachOverlay
sourceRect: Qt.rect(
0,
0,
seachOverlay.width,
seachOverlay.height
)
}
// Background
Item {
id: burryOverlay
visible: false
opacity: 0
anchors.fill: parent
clip: true
Repeater {
anchors.fill: parent
model: 5
FastBlur {
anchors.fill: parent
source: effectSource
radius: 30
}
}
Rectangle {
anchors.fill: parent
color: inactivePalette.highlight
opacity: 0.75
}
}
// Header buttons
Loader {
height: active ? searchBox.height : 0
- width: parent.width - (searchBox ? searchBox.labelWidth : 0)
+ width: parent.width
anchors.right: parent.parent.right
y: -searchBox.height
clip: true
active: searchState.activeState
sourceComponent: JamiSearch.ToolBar {}
}
// Content
Layouts.ColumnLayout {
anchors.fill: parent
spacing: 0
Item {
Layouts.Layout.fillWidth: true
Layouts.Layout.preferredHeight: 2*searchBox.height
}
// Display a welcome message when the user uses the app for the first time
JamiSearch.FirstRun {
id: firstRun
visible: active
- active: searchState.firstSearchState
+ active: searchState.displayWelcome
Layouts.Layout.fillWidth: true
Layouts.Layout.preferredHeight: active ? parent.height* 0.4 : 0
Layouts.Layout.maximumHeight: active ? parent.height* 0.4 : 0
}
// Display an icon for each search categories and match the colors with
// colored symbols in each search entry
JamiSearch.MatchCategories {
id: filterList
active: searchState.displaySearchCategories
opacity: searchView.count > 0 ? 1 : 0
Layouts.Layout.fillWidth: true
Layouts.Layout.preferredHeight: active ?
30 + Kirigami.Units.fontMetrics.height*1.5 : 0
}
// Display some tips and help to new users
JamiSearch.SearchTip {
active: searchState.displaySearchHelp
Layouts.Layout.fillWidth: true
Layouts.Layout.preferredHeight: active ? height : 0
Layouts.Layout.maximumHeight: active ? height : 0
}
// Display the results for the current query
JamiSearch.Results {
id: searchView
Layouts.Layout.fillWidth: true
Layouts.Layout.fillHeight: true
z: 99999999
}
}
// When the user presses Return with nothing selected, print a message
Rectangle {
id: notFoundMessage
z: 999999999
visible: false
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottomMargin: 20
radius: 5
width: parent.width * 0.80
height: errorLabel.implicitHeight + 20
color: Kirigami.Theme.textColor
opacity: 0
Behavior on opacity {
NumberAnimation {duration: 150; easing.type: Easing.OutQuad}
}
Timer {
id: errorMessageTimer
running: false
interval: 3000
repeat: false
onTriggered: {
notFoundMessage.visible = false
notFoundMessage.opacity = 0
}
}
Text {
id: errorLabel
width: parent.width
y: 10
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
color: inactivePalette.base
text: i18n("Cannot select this person because it was not found")
}
}
onDisplayNotFoundMessage: {
errorMessageTimer.running = true
notFoundMessage.visible = true
notFoundMessage.opacity = 1
}
CheckBox {
z: 199999999
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.margins: 10
text: i18n("Hide and do not show again")
checked: false
checkable: true
visible: displayTips.showFirstTip && searchStateGroup.state == "firstSearch"
onCheckStateChanged: {
searchBox.searchFocus = false
displayTips.showFirstTip = false
}
}
// Search
StateGroup {
id: searchStateGroup
states: [
State {
name: ""
when: searchState.inactiveState
- ParentChange {
- target: seachOverlay
- parent: topLevel
- }
-
- PropertyChanges {
- target: seachOverlay
- anchors.fill: parent
- }
-
PropertyChanges {
target: burryOverlay
visible: false
opacity: 0
}
},
State {
name: "searchActive"
when: searchState.activeState
-// PropertyChanges {
-// target: seachOverlay
-// anchors.fill: parent
-// width: undefined
-// height: undefined
-// }
-
PropertyChanges {
target: burryOverlay
visible: true
opacity: 1
}
-
- PropertyChanges {
- target: effectSource
- sourceRect: Qt.rect(0, 0, parent.width, parent.height)
- }
},
State {
name: "firstSearch"
extend: "searchActive"
when: searchState.firstSearchState
-
-// PropertyChanges {
-// target: seachOverlay
-// anchors.fill: undefined
-// width: applicationWindow().contentItem.width
-// height: applicationWindow().contentItem.height
-// }
-//
-// PropertyChanges {
-// target: searchBox
-// searchFocus: true
-// }
}
]
transitions: [
Transition {
to: "searchActive"
NumberAnimation {
properties: "opacity"
easing.type: Easing.InQuad
duration: 200
loops: 1
}
NumberAnimation {
properties: "width,height"
easing.type: Easing.InQuad
duration: 0
loops: 1
}
}
]
}
}
diff --git a/src/jamisearch/qml/searchstate.qml b/src/jamisearch/qml/searchstate.qml
index 8a39fd55..8e062f74 100644
--- a/src/jamisearch/qml/searchstate.qml
+++ b/src/jamisearch/qml/searchstate.qml
@@ -1,124 +1,126 @@
/***************************************************************************
* Copyright (C) 2018 by Bluesystems *
* Author : Emmanuel Lepage Vallee *
* *
* This program 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. *
* *
* This program 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 this program. If not, see . *
**************************************************************************/
import QtQuick 2.7
/**
* Avoids a spaghetti mess of multi line, multi state expressions to define
* how to display the search popup.
*/
QtObject {
// States
property bool inactiveState: false
property bool firstSearchState: false
property bool activeState: false
property string state: "inactive"
+ property bool display: _delayed && (firstSearchState || activeState)
// Extra widgets
property bool displaySearchHelp: false
property bool displaySearchCategories: false
+ property bool displayWelcome: searchEmpty && firstSearchState
// External status
property bool searchEmpty: false
property bool focussed: false
// Geometry
property var normalSearchArea: undefined
property var firstSearchArea: undefined
// Internal
property bool _delayed: false
property bool _hasSearched: false
property var _c1: Connections {
target: displayTips
onShowFirstTipChanged: _evalState()
}
property var _c2: Connections {
target: RingSession.peersTimelineModel
onEmptyChanged: _evalState()
}
function _evalState() {
// Do not evaluate during initialization as it wont have the
// whole picture of what is and isn't set.
if (!_delayed)
return
var isFirst = displayTips.showFirstTip
&& RingSession.peersTimelineModel.empty
// State
if (isFirst) {
firstSearchState = true
activeState = false
inactiveState = false
}
else if (focussed) {
firstSearchState = false
activeState = true
inactiveState = false
}
else {
firstSearchState = false
activeState = false
inactiveState = true
}
// Extra widgets
displaySearchHelp = activeState && searchEmpty
displaySearchCategories = activeState && (!searchEmpty)
var newState = ""
if (firstSearchState)
newState = "firstSearch"
else if (activeState)
newState = "active"
else
newState = "inactive"
// Prevent too many signals
if (newState != state)
state = newState
}
onFocussedChanged: _evalState()
onSearchEmptyChanged: {
_hasSearched = _hasSearched || !searchEmpty
_evalState()
}
/**
* QML properties are evaluated in a random order, this exists to stop
* trying to handle everything.
*
* Keep in mind that some other components already have hacks to handle
* this. So this has to be done /after/ those hacks
* (which cannot be detected), hence the timer.
*/
property var _t: Timer {
repeat: false
running: true
- interval: 0
+ interval: 100
onTriggered: {
_delayed = true
_evalState()
}
}
}
diff --git a/views/basic/qml/basic.qml b/views/basic/qml/basic.qml
index 207fd414..e7e7f20a 100644
--- a/views/basic/qml/basic.qml
+++ b/views/basic/qml/basic.qml
@@ -1,155 +1,158 @@
/*
* Copyright 2018 Fabian Riethmayer
* Copyright 2019 Emmanuel Lepage
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 3, or
* (at your option) any later version.
*
* This program 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.6 as Kirigami
import net.lvindustries.ringqtquick 1.0 as RingQtQuick
import org.kde.ringkde.basicview 1.0 as BasicView
import org.kde.ringkde.jamicontactview 1.0 as JamiContactView
import org.kde.ringkde.jamiwizard 1.0 as JamiWizard
import org.kde.ringkde.jamikdeintegration 1.0 as JamiKDEIntegration
import QtQuick.Controls.Material 2.3
Kirigami.ApplicationWindow {
width: 320
height: 600
id: root
// Localization is currently broken with the Material theme
function i18n(t) {return t;}
RingQtQuick.SharedModelLocker {
id: mainPage
onChanged: {
chat.boo.timelineModel = timelineModel
if (!currentIndividual)
return;
var idx = RingSession.peersTimelineModel.individualIndex(currentIndividual)
list.currentIndex = idx.row
}
}
BasicView.ActionCollection {
id: actionCollection
}
BasicView.Contacts {
id : mydata
Component.onCompleted: {
chat.model = mydata.get(3)
}
}
pageStack.initialPage: [list, chat]
pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar
pageStack.globalToolBar.preferredHeight: Kirigami.Units.gridUnit * 3
pageStack.defaultColumnWidth: root.width < 320 ? root.width : 320
BasicView.ListPage {
id: list
model: RingSession.peersTimelineModel
}
BasicView.ChatPage {
id: chat
}
contextDrawer: Kirigami.ContextDrawer {
id: contextDrawer
}
globalDrawer: BasicView.GlobalDrawer {
id: globalDrawer
}
JamiKDEIntegration.WindowEvent {
id: events
onRequestsConfigureAccounts: {
var component = Qt.createComponent("qrc:/account/qml/accountdialog.qml")
if (component.status == Component.Ready) {
var window = component.createObject(applicationWindow().contentItem)
window.open()
}
else
console.log("ERROR", component.status, component.errorString())
}
onRequestsHideWindow: {
hide()
}
onRequestsWizard: {
globalDrawer.drawerOpen = false
wizardLoader.visible = true
wizardLoader.active = true
}
}
/**
* Display the wizard when all accounts are deleted.
*/
JamiWizard.Policies {
id: wizardPolicies
}
Loader {
id: wizardLoader
active: false
anchors.fill: parent
z: 999999
onActiveChanged: {
if ( list.displayWelcome && !active)
list.search()
}
sourceComponent: JamiWizard.Wizard {
anchors.fill: parent
z: 999999
onVisibleChanged: {
if (!visible) {
wizardLoader.visible = false
wizardLoader.active = false
}
}
onWizardFinished: {
wizardLoader.active = false
}
}
}
Timer {
interval: 0
running: true
repeat: false
onTriggered: {
- wizardLoader.active = wizardPolicies.displayWizard
+ if (wizardPolicies.displayWizard)
+ wizardLoader.active = true
+ else if (list.displayWelcome)
+ list.search()
}
}
}
diff --git a/views/basic/qml/listpage.qml b/views/basic/qml/listpage.qml
index e89d791d..afbf1b78 100644
--- a/views/basic/qml/listpage.qml
+++ b/views/basic/qml/listpage.qml
@@ -1,132 +1,141 @@
/*
* Copyright 2018 Fabian Riethmayer
* Copyright 2019 Emmanuel Lepage
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 3, or
* (at your option) any later version.
*
* This program 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.6
import QtQuick.Controls 2.2 as Controls
import org.kde.kirigami 2.4 as Kirigami
import QtQuick.Layouts 1.2 as Layouts
import org.kde.ringkde.basicview 1.0 as BasicView
import org.kde.ringkde.jamitroubleshooting 1.0 as JamiTroubleShooting
import org.kde.ringkde.jamisearch 1.0 as JamiSearch
Kirigami.Page {
id: peerListPage
property alias currentIndex: list.currentIndex;
property alias model: list.model
property bool displayWelcome: false
spacing: 0
leftPadding: 0; rightPadding: 0; topPadding: 0;bottomPadding: 0; padding: 0
signal search()
Kirigami.Theme.colorSet: Kirigami.Theme.View
header: Layouts.ColumnLayout {
visible: globalTroubleshoot.sourceComponent != null
height: visible && globalTroubleshoot.active ? implicitHeight : 0
width: peerListPage.width
spacing: Kirigami.Units.largeSpacing
JamiTroubleShooting.GlobalTroubleshoot {
id: globalTroubleshoot
Layouts.Layout.fillWidth: true
Layouts.Layout.margins: Kirigami.Units.largeSpacing
}
Item {
visible: globalTroubleshoot.sourceComponent != null
height: 10
}
}
title: i18n("Address book")
background: Rectangle {
color: Kirigami.Theme.backgroundColor
}
titleDelegate: Item {
id: header
implicitHeight: parent.parent.height - 2*Kirigami.Units.largeSpacing
implicitWidth: 10
JamiSearch.SearchBox {
id: headerSearchbox
searchView: _searchView
anchors.centerIn: parent
anchors.margins: Kirigami.Units.largeSpacing
width: parent.width - 2 * Kirigami.Units.largeSpacing
height: headerSearchbox.focus ? parent.height : parent.height * 1.5
z: 9999
Connections {
target: peerListPage
onSearch: headerSearchbox.searchFocus = true
}
+
+ /*Connections {
+ target: peerListPage
+ onDisplayWelcomeChanged: {
+ if (peerListPage.displayWelcome)
+ headerSearchbox.searchFocus = true
+ }
+ }*/
+
}
JamiSearch.Overlay {
id: _searchView
source: peerListPage
searchBox: headerSearchbox
width: peerListPage.width
height: peerListPage.height + header.height
x: -(peerListPage.width - header.width)
y: -Kirigami.Units.largeSpacing
onDisplayWelcomeChanged: {
peerListPage.displayWelcome = displayWelcome
}
onContactMethodSelected: {
mainPage.currentContactMethod = cm
pageStack.push(chat)
var idx = RingSession.peersTimelineModel.individualIndex(cm.individual)
list.currentIndex = idx.row
}
//HACK obey god dammit
onHeightChanged: {
height = peerListPage.height + header.height
x = -(peerListPage.width - header.width)
width = peerListPage.width
}
//HACK obey god dammit
onActiveChanged: {
if (!active)
return
width = peerListPage.width
height = peerListPage.height + header.height
x = -(peerListPage.width - header.width)
}
z: 9998
}
}
BasicView.List {
id: list
width: parent.width
height: parent.height
}
}