mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-07 05:58:28 -04:00
Squashed commit of the following:
commit990d86d481Author: bbedward <bbedward@gmail.com> Date: Sat Jul 18 10:43:22 2026 -0400 flake: update-common commit526cb157fdAuthor: bbedward <bbedward@gmail.com> Date: Thu Jul 16 17:56:40 2026 -0400 i18n: update sync scrirpt for dank-qml-common commit92ba96d9f9Author: bbedward <bbedward@gmail.com> Date: Thu Jul 16 09:24:37 2026 -0400 qs: integrate with dank-qml-common
This commit is contained in:
@@ -1,271 +1,3 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
import qs.DankCommon.Widgets as DankCommon
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
KeyNavigation.tab: keyNavigationTab
|
||||
KeyNavigation.backtab: keyNavigationBacktab
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
locationInput.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
property string currentLocation: ""
|
||||
property string placeholderText: I18n.tr("Search for a location...")
|
||||
property bool _internalChange: false
|
||||
property bool isLoading: false
|
||||
property string currentSearchText: ""
|
||||
property Item keyNavigationTab: null
|
||||
property Item keyNavigationBacktab: null
|
||||
|
||||
signal locationSelected(string displayName, string coordinates)
|
||||
|
||||
function resetSearchState() {
|
||||
locationSearchTimer.stop();
|
||||
dropdownHideTimer.stop();
|
||||
isLoading = false;
|
||||
searchResultsModel.clear();
|
||||
}
|
||||
|
||||
// CJK city names are commonly two code points (北京, 東京, 서울).
|
||||
function canSearch(t) {
|
||||
return t.length > 2 || (t.length >= 2 && /[-ヿ㐀-䶿一-鿿豈-가-]/.test(t));
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
height: searchInputField.height + (searchDropdown.visible ? searchDropdown.height : 0)
|
||||
|
||||
ListModel {
|
||||
id: searchResultsModel
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: locationSearchTimer
|
||||
|
||||
interval: 500
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (root.canSearch(locationInput.text)) {
|
||||
searchResultsModel.clear();
|
||||
root.isLoading = true;
|
||||
const searchLocation = locationInput.text;
|
||||
root.currentSearchText = searchLocation;
|
||||
const encodedLocation = encodeURIComponent(searchLocation);
|
||||
const searchUrl = "https://nominatim.openstreetmap.org/search?q=" + encodedLocation + "&format=json&limit=5&addressdetails=1";
|
||||
Proc.runCommand("locationSearch", [Proc.dmsBin, "dl", "-4", "--timeout", "10", searchUrl], (output, exitCode) => {
|
||||
root.isLoading = false;
|
||||
if (exitCode !== 0) {
|
||||
searchResultsModel.clear();
|
||||
return;
|
||||
}
|
||||
if (root.currentSearchText !== locationInput.text)
|
||||
return;
|
||||
const raw = output.trim();
|
||||
searchResultsModel.clear();
|
||||
if (!raw || raw[0] !== "[") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = JSON.parse(raw);
|
||||
if (data.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < Math.min(data.length, 5); i++) {
|
||||
const location = data[i];
|
||||
if (location.display_name && location.lat && location.lon) {
|
||||
const parts = location.display_name.split(', ');
|
||||
let cleanName = parts[0];
|
||||
if (parts.length > 1) {
|
||||
const state = parts[parts.length - 2];
|
||||
if (state && state !== cleanName)
|
||||
cleanName += `, ${state}`;
|
||||
}
|
||||
const query = `${location.lat},${location.lon}`;
|
||||
searchResultsModel.append({
|
||||
"name": cleanName,
|
||||
"query": query
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: dropdownHideTimer
|
||||
|
||||
interval: 200
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (!locationInput.getActiveFocus() && !searchDropdown.hovered)
|
||||
root.resetSearchState();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: searchInputField
|
||||
|
||||
width: parent.width
|
||||
height: 48
|
||||
|
||||
DankTextField {
|
||||
id: locationInput
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
leftIconName: "search"
|
||||
placeholderText: root.placeholderText
|
||||
text: ""
|
||||
backgroundColor: Theme.surfaceVariant
|
||||
normalBorderColor: Theme.primarySelected
|
||||
focusedBorderColor: Theme.primary
|
||||
keyNavigationTab: root.keyNavigationTab
|
||||
keyNavigationBacktab: root.keyNavigationBacktab
|
||||
onTextEdited: {
|
||||
if (root._internalChange)
|
||||
return;
|
||||
if (getActiveFocus()) {
|
||||
if (root.canSearch(text)) {
|
||||
root.isLoading = true;
|
||||
locationSearchTimer.restart();
|
||||
} else {
|
||||
root.resetSearchState();
|
||||
}
|
||||
}
|
||||
}
|
||||
onFocusStateChanged: hasFocus => {
|
||||
if (hasFocus) {
|
||||
dropdownHideTimer.stop();
|
||||
} else {
|
||||
dropdownHideTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: root.isLoading ? "hourglass_empty" : (searchResultsModel.count > 0 ? "check_circle" : "error")
|
||||
size: Theme.iconSize - 4
|
||||
color: root.isLoading ? Theme.surfaceVariantText : (searchResultsModel.count > 0 ? Theme.primary : Theme.error)
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
opacity: (locationInput.getActiveFocus() && root.canSearch(locationInput.text)) ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: searchDropdown
|
||||
|
||||
property bool hovered: false
|
||||
|
||||
width: parent.width
|
||||
height: Math.min(Math.max(searchResultsModel.count * 38 + Theme.spacingS * 2, 50), 200)
|
||||
y: searchInputField.height
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
border.color: Theme.primarySelected
|
||||
border.width: 1
|
||||
visible: locationInput.getActiveFocus() && root.canSearch(locationInput.text) && (searchResultsModel.count > 0 || root.isLoading)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
parent.hovered = true;
|
||||
dropdownHideTimer.stop();
|
||||
}
|
||||
onExited: {
|
||||
parent.hovered = false;
|
||||
if (!locationInput.getActiveFocus())
|
||||
dropdownHideTimer.start();
|
||||
}
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingS
|
||||
|
||||
DankListView {
|
||||
id: searchResultsList
|
||||
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
model: searchResultsModel
|
||||
spacing: Theme.spacingXXS
|
||||
|
||||
delegate: StyledRect {
|
||||
width: searchResultsList.width
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: resultMouseArea.containsMouse ? Theme.surfaceLight : Theme.withAlpha(Theme.surfaceLight, 0)
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankIcon {
|
||||
name: "place"
|
||||
size: Theme.iconSize - 6
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: model.name || "Unknown"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
elide: Text.ElideRight
|
||||
width: parent.width - 30
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: resultMouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root._internalChange = true;
|
||||
const selectedName = model.name;
|
||||
const selectedQuery = model.query;
|
||||
locationInput.text = selectedName;
|
||||
root.locationSelected(selectedName, selectedQuery);
|
||||
root.resetSearchState();
|
||||
locationInput.setFocus(false);
|
||||
root._internalChange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: root.isLoading ? "Searching..." : "No locations found"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
visible: searchResultsList.count === 0 && root.canSearch(locationInput.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DankCommon.DankLocationSearch {}
|
||||
|
||||
Reference in New Issue
Block a user