Move Elsewhen into Omarchy as omarchy.elsewhen (#13429)
* Move Elsewhen into Omarchy as omarchy.elsewhen The world clock ships in the shell tree instead of its own package. A migration renames existing bar entries with their settings and removes the retired package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove Elsewhen's shelved Earth row, overlap band and sky tint Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tidy Elsewhen's models, data helper and docs, and drop currency Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Restructure Elsewhen's panel and globe on the shared shell components Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show Elsewhen's bar globe upright Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use the shared city search for Elsewhen's globe jump bar Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep legacy Elsewhen entries single and retry offline geocodes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fetch Elsewhen's weather with curl instead of a Python helper Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5c7cef1e78
commit
e7218e36f2
37 files changed
+6780
-155
No files matched your search
@@ -0,0 +1,98 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Ui
|
||||
import "Model.js" as Model
|
||||
|
||||
// A button that opens into a city search: a field, then the matching cities
|
||||
// with their zone and offset. Arrows move the selection, Return picks it,
|
||||
// Escape backs out. Inline rather than a dropdown so the results grow the
|
||||
// panel instead of running off the bottom of the screen.
|
||||
Column {
|
||||
id: search
|
||||
|
||||
// [{ label, value }] from Model.zoneOptions.
|
||||
property var options: []
|
||||
property int limit: 6
|
||||
// Zone id -> offset text; read inside a binding, so its dependencies track.
|
||||
property var offsetLabel: function(zoneId) { return "" }
|
||||
property bool loading: false
|
||||
property string buttonText: "+ Add a city"
|
||||
property string placeholderText: "Search cities\u2026"
|
||||
property string loadingText: "Loading zones\u2026"
|
||||
property real fontSize: Style.font.bodySmall
|
||||
property color foreground: Color.foreground
|
||||
property color dim: Qt.darker(foreground, 1.55)
|
||||
property color fainter: Qt.darker(foreground, 2.1)
|
||||
property string fontFamily: Style.font.family
|
||||
|
||||
// False when the host shows CityMatches elsewhere.
|
||||
property bool inlineResults: true
|
||||
|
||||
property bool active: false
|
||||
readonly property string query: field.text
|
||||
readonly property var matches: active ? Model.searchZones(options, query, limit) : []
|
||||
// An index, not the match itself: the list is rebuilt on every keystroke.
|
||||
property int selectedIndex: 0
|
||||
|
||||
signal picked(string label, string id)
|
||||
signal dismissed()
|
||||
|
||||
onQueryChanged: selectedIndex = 0
|
||||
onMatchesChanged: if (selectedIndex >= matches.length) selectedIndex = 0
|
||||
|
||||
function start() {
|
||||
selectedIndex = 0
|
||||
active = true
|
||||
Qt.callLater(function() { field.text = ""; field.forceActiveFocus() })
|
||||
}
|
||||
|
||||
// The hidden field would keep the keyboard, so the host takes it back on dismissed.
|
||||
function stop() {
|
||||
active = false
|
||||
field.text = ""
|
||||
dismissed()
|
||||
}
|
||||
|
||||
function pick(match) {
|
||||
picked(match.label, match.value)
|
||||
stop()
|
||||
}
|
||||
|
||||
function pickSelected() {
|
||||
if (matches.length > 0) pick(matches[Util.clamp(selectedIndex, 0, matches.length - 1)])
|
||||
}
|
||||
|
||||
spacing: Style.spacing.md
|
||||
|
||||
Button {
|
||||
width: parent.width
|
||||
// Matches the field, so opening the search does not shift the layout.
|
||||
height: field.implicitHeight
|
||||
visible: !search.active
|
||||
text: search.buttonText
|
||||
fontSize: search.fontSize
|
||||
foreground: search.foreground
|
||||
fontFamily: search.fontFamily
|
||||
bordered: true
|
||||
onClicked: search.start()
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: field
|
||||
visible: search.active
|
||||
width: parent.width
|
||||
placeholderText: search.placeholderText
|
||||
foreground: search.foreground
|
||||
Keys.onEscapePressed: search.stop()
|
||||
Keys.onReturnPressed: search.pickSelected()
|
||||
Keys.onEnterPressed: search.pickSelected()
|
||||
Keys.onUpPressed: search.selectedIndex = Model.moveSelection(search.selectedIndex, -1, search.matches.length)
|
||||
Keys.onDownPressed: search.selectedIndex = Model.moveSelection(search.selectedIndex, 1, search.matches.length)
|
||||
}
|
||||
|
||||
CityMatches {
|
||||
width: parent.width
|
||||
visible: search.active && search.inlineResults
|
||||
citySearch: search
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user