mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-29 06:08:48 +03:00
Fix some issues with completer
This commit is contained in:
parent
c2eea5cb55
commit
29625ae253
5 changed files with 146 additions and 70 deletions
|
@ -53,7 +53,6 @@ Rectangle {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: TimelineManager
|
target: TimelineManager
|
||||||
|
|
||||||
onCallStateChanged: {
|
onCallStateChanged: {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case WebRTCState.INITIATING:
|
case WebRTCState.INITIATING:
|
||||||
|
|
|
@ -9,105 +9,120 @@ Popup {
|
||||||
property int currentIndex: -1
|
property int currentIndex: -1
|
||||||
property string completerName
|
property string completerName
|
||||||
property var completer
|
property var completer
|
||||||
|
property bool bottomToTop: true
|
||||||
|
|
||||||
function up() {
|
function up() {
|
||||||
currentIndex = currentIndex - 1;
|
if (bottomToTop)
|
||||||
if (currentIndex == -2)
|
down_();
|
||||||
currentIndex = repeater.count - 1;
|
else
|
||||||
|
up_();
|
||||||
}
|
}
|
||||||
|
|
||||||
function down() {
|
function down() {
|
||||||
|
if (bottomToTop)
|
||||||
|
up_();
|
||||||
|
else
|
||||||
|
down_();
|
||||||
|
}
|
||||||
|
|
||||||
|
function up_() {
|
||||||
|
currentIndex = currentIndex - 1;
|
||||||
|
if (currentIndex == -2)
|
||||||
|
currentIndex = listView.count - 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function down_() {
|
||||||
currentIndex = currentIndex + 1;
|
currentIndex = currentIndex + 1;
|
||||||
if (currentIndex >= repeater.count)
|
if (currentIndex >= listView.count)
|
||||||
currentIndex = -1;
|
currentIndex = -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentCompletion() {
|
function currentCompletion() {
|
||||||
if (currentIndex > -1 && currentIndex < repeater.count)
|
if (currentIndex > -1 && currentIndex < listView.count)
|
||||||
return completer.completionAt(currentIndex);
|
return completer.completionAt(currentIndex);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onCompleterNameChanged: {
|
onCompleterNameChanged: {
|
||||||
if (completerName)
|
if (completerName) {
|
||||||
completer = TimelineManager.timeline.input.completerFor(completerName);
|
completer = TimelineManager.timeline.input.completerFor(completerName);
|
||||||
else
|
completer.setSearchString("");
|
||||||
|
} else {
|
||||||
completer = undefined;
|
completer = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
padding: 0
|
padding: 0
|
||||||
onAboutToShow: currentIndex = -1
|
onAboutToShow: currentIndex = -1
|
||||||
|
height: listView.contentHeight
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
onTimelineChanged: completer = null
|
onTimelineChanged: completer = null
|
||||||
target: TimelineManager
|
target: TimelineManager
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ListView {
|
||||||
|
id: listView
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
implicitWidth: contentItem.childrenRect.width
|
||||||
|
model: completer
|
||||||
|
verticalLayoutDirection: popup.bottomToTop ? ListView.BottomToTop : ListView.TopToBottom
|
||||||
|
|
||||||
Repeater {
|
delegate: Rectangle {
|
||||||
id: repeater
|
color: model.index == popup.currentIndex ? colors.highlight : colors.base
|
||||||
|
height: chooser.childrenRect.height + 4
|
||||||
|
implicitWidth: chooser.childrenRect.width + 4
|
||||||
|
|
||||||
model: completer
|
DelegateChooser {
|
||||||
|
id: chooser
|
||||||
|
|
||||||
delegate: Rectangle {
|
roleValue: popup.completerName
|
||||||
color: model.index == popup.currentIndex ? colors.window : colors.alternateBase
|
anchors.centerIn: parent
|
||||||
height: chooser.childrenRect.height + 4
|
|
||||||
width: chooser.childrenRect.width + 4
|
|
||||||
|
|
||||||
DelegateChooser {
|
DelegateChoice {
|
||||||
id: chooser
|
roleValue: "user"
|
||||||
|
|
||||||
roleValue: popup.completerName
|
RowLayout {
|
||||||
anchors.centerIn: parent
|
id: del
|
||||||
|
|
||||||
DelegateChoice {
|
anchors.centerIn: parent
|
||||||
roleValue: "user"
|
|
||||||
|
|
||||||
RowLayout {
|
Avatar {
|
||||||
id: del
|
height: 24
|
||||||
|
width: 24
|
||||||
anchors.centerIn: parent
|
displayName: model.displayName
|
||||||
|
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||||
Avatar {
|
}
|
||||||
height: 24
|
|
||||||
width: 24
|
|
||||||
displayName: model.displayName
|
|
||||||
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: model.displayName
|
|
||||||
color: colors.text
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: model.displayName
|
||||||
|
color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DelegateChoice {
|
}
|
||||||
roleValue: "emoji"
|
|
||||||
|
|
||||||
RowLayout {
|
DelegateChoice {
|
||||||
id: del
|
roleValue: "emoji"
|
||||||
|
|
||||||
anchors.centerIn: parent
|
RowLayout {
|
||||||
|
id: del
|
||||||
|
|
||||||
Label {
|
anchors.centerIn: parent
|
||||||
text: model.unicode
|
|
||||||
color: colors.text
|
|
||||||
font: Settings.emojiFont
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: model.shortName
|
text: model.unicode
|
||||||
color: colors.text
|
color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
|
||||||
}
|
font: Settings.emojiFont
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: model.shortName
|
||||||
|
color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -141,7 +156,7 @@ Popup {
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: colors.alternateBase
|
color: colors.base
|
||||||
implicitHeight: popup.contentHeight
|
implicitHeight: popup.contentHeight
|
||||||
implicitWidth: popup.contentWidth
|
implicitWidth: popup.contentWidth
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,6 @@ ListView {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: chat
|
target: chat
|
||||||
|
|
||||||
onMovementEnded: {
|
onMovementEnded: {
|
||||||
if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height)
|
if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height)
|
||||||
chat.model.currentIndex = index;
|
chat.model.currentIndex = index;
|
||||||
|
|
|
@ -131,7 +131,6 @@ Page {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: TimelineManager
|
target: TimelineManager
|
||||||
|
|
||||||
onNewDeviceVerificationRequest: {
|
onNewDeviceVerificationRequest: {
|
||||||
var dialog = deviceVerificationDialog.createObject(timelineRoot, {
|
var dialog = deviceVerificationDialog.createObject(timelineRoot, {
|
||||||
"flow": flow
|
"flow": flow
|
||||||
|
@ -142,7 +141,6 @@ Page {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: TimelineManager.timeline
|
target: TimelineManager.timeline
|
||||||
|
|
||||||
onOpenProfile: {
|
onOpenProfile: {
|
||||||
var userProfile = userProfileComponent.createObject(timelineRoot, {
|
var userProfile = userProfileComponent.createObject(timelineRoot, {
|
||||||
"profile": profile
|
"profile": profile
|
||||||
|
|
|
@ -43,29 +43,94 @@ struct trie
|
||||||
return ret;
|
return ret;
|
||||||
else {
|
else {
|
||||||
auto temp = t.valuesAndSubvalues(limit - ret.size());
|
auto temp = t.valuesAndSubvalues(limit - ret.size());
|
||||||
ret.insert(ret.end(), temp.begin(), temp.end());
|
for (auto &&v : temp) {
|
||||||
|
if (ret.size() >= limit)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
|
||||||
|
ret.push_back(std::move(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Value> search(const QVector<Key> &keys, size_t limit) const
|
std::vector<Value> search(const QVector<Key> &keys,
|
||||||
|
size_t limit,
|
||||||
|
size_t max_distance = 2) const
|
||||||
{
|
{
|
||||||
std::vector<Value> ret;
|
std::vector<Value> ret;
|
||||||
auto t = this;
|
if (!limit)
|
||||||
int i = 0;
|
return ret;
|
||||||
for (; i < (int)keys.size(); i++) {
|
|
||||||
if (auto e = t->next.find(keys[i]); e != t->next.end()) {
|
auto append = [&ret, limit](std::vector<Value> &&in) {
|
||||||
t = &e->second;
|
for (auto &&v : in) {
|
||||||
} else {
|
if (ret.size() >= limit)
|
||||||
t = nullptr;
|
return;
|
||||||
break;
|
|
||||||
|
if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
|
||||||
|
ret.push_back(std::move(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
auto t = this;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < (int)keys.size(); i++) {
|
||||||
|
if (auto e = t->next.find(keys[i]); e != t->next.end()) {
|
||||||
|
t = &e->second;
|
||||||
|
} else {
|
||||||
|
t = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t) {
|
||||||
|
ret = t->valuesAndSubvalues(limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t) {
|
if (max_distance && keys.size() < static_cast<int>(limit) && keys.size() > 1) {
|
||||||
ret = t->valuesAndSubvalues(limit);
|
max_distance -= 1;
|
||||||
|
|
||||||
|
// swap chars case
|
||||||
|
if (keys.size() >= 2) {
|
||||||
|
auto t = this;
|
||||||
|
for (int i = 1; i >= 0; i--) {
|
||||||
|
if (auto e = t->next.find(keys[i]); e != t->next.end()) {
|
||||||
|
t = &e->second;
|
||||||
|
} else {
|
||||||
|
t = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t) {
|
||||||
|
append(t->search(
|
||||||
|
keys.mid(2), (limit - ret.size()) * 2, max_distance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete character case
|
||||||
|
append(this->search(keys.mid(1), (limit - ret.size()) * 2, max_distance));
|
||||||
|
|
||||||
|
// substitute and insert cases
|
||||||
|
for (const auto &[k, t] : this->next) {
|
||||||
|
if (k == keys[0] || ret.size() >= limit)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// substitute
|
||||||
|
append(this->search(keys.mid(1), limit - ret.size(), max_distance));
|
||||||
|
|
||||||
|
if (ret.size() >= limit)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// insert
|
||||||
|
append(this->search(keys, limit - ret.size(), max_distance));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue