mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-27 06:52:50 -05:00
General code cleanups
This commit is contained in:
@@ -31,7 +31,6 @@ PanelWindow {
|
||||
show();
|
||||
}
|
||||
|
||||
// Proper layer shell configuration
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: isVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
@@ -39,7 +38,6 @@ PanelWindow {
|
||||
visible: isVisible
|
||||
color: "transparent"
|
||||
|
||||
// Full screen overlay setup for proper focus
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
@@ -47,7 +45,6 @@ PanelWindow {
|
||||
bottom: true
|
||||
}
|
||||
|
||||
// App launcher logic
|
||||
AppLauncher {
|
||||
id: appLauncher
|
||||
|
||||
@@ -59,12 +56,10 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Background click to close (no visual background)
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: appDrawerPopout.isVisible
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the launcher panel
|
||||
var localPos = mapToItem(launcherLoader, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > launcherLoader.width || localPos.y < 0 || localPos.y > launcherLoader.height)
|
||||
appDrawerPopout.hide();
|
||||
@@ -72,7 +67,6 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Main launcher panel with asynchronous loading
|
||||
Loader {
|
||||
id: launcherLoader
|
||||
|
||||
@@ -108,11 +102,9 @@ PanelWindow {
|
||||
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusXLarge
|
||||
// Remove layer rendering for better performance
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
|
||||
// Material 3 elevation with multiple layers
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -3
|
||||
@@ -142,7 +134,6 @@ PanelWindow {
|
||||
z: -1
|
||||
}
|
||||
|
||||
// Content with focus management
|
||||
Item {
|
||||
id: keyHandler
|
||||
|
||||
@@ -153,7 +144,6 @@ PanelWindow {
|
||||
forceActiveFocus();
|
||||
|
||||
}
|
||||
// Handle keyboard shortcuts
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
appDrawerPopout.hide();
|
||||
@@ -174,7 +164,6 @@ PanelWindow {
|
||||
appLauncher.launchSelected();
|
||||
event.accepted = true;
|
||||
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) {
|
||||
// User started typing, focus search field and pass the character
|
||||
searchField.forceActiveFocus();
|
||||
searchField.insertText(event.text);
|
||||
event.accepted = true;
|
||||
@@ -214,7 +203,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Enhanced search field
|
||||
DankTextField {
|
||||
id: searchField
|
||||
|
||||
@@ -333,7 +321,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// App grid/list container with enhanced styling
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: {
|
||||
@@ -347,7 +334,6 @@ PanelWindow {
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
|
||||
border.width: 1
|
||||
|
||||
// List view
|
||||
DankListView {
|
||||
id: appList
|
||||
|
||||
@@ -372,7 +358,6 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Grid view
|
||||
DankGridView {
|
||||
id: appGrid
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import qs.Widgets
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Public interface
|
||||
property string searchQuery: ""
|
||||
property string selectedCategory: "All"
|
||||
property string viewMode: "list" // "list" or "grid"
|
||||
@@ -18,7 +17,6 @@ Item {
|
||||
property bool debounceSearch: true
|
||||
property int debounceInterval: 50
|
||||
property bool keyboardNavigationActive: false
|
||||
// Categories (computed from AppSearchService)
|
||||
property var categories: {
|
||||
var allCategories = AppSearchService.getAllCategories().filter((cat) => {
|
||||
return cat !== "Education" && cat !== "Science";
|
||||
@@ -28,18 +26,13 @@ Item {
|
||||
return cat !== "All";
|
||||
}));
|
||||
}
|
||||
// Category icons (computed from AppSearchService)
|
||||
property var categoryIcons: categories.map((category) => {
|
||||
return AppSearchService.getCategoryIcon(category);
|
||||
})
|
||||
// App usage ranking helper
|
||||
property var appUsageRanking: Prefs.appUsageRanking
|
||||
// Internal model
|
||||
property alias model: filteredModel
|
||||
// Watch AppSearchService.applications changes via property binding
|
||||
property var _watchApplications: AppSearchService.applications
|
||||
|
||||
// Signals
|
||||
signal appLaunched(var app)
|
||||
signal categorySelected(string category)
|
||||
signal viewModeSelected(string mode)
|
||||
@@ -50,7 +43,6 @@ Item {
|
||||
keyboardNavigationActive = false;
|
||||
var apps = [];
|
||||
if (searchQuery.length === 0) {
|
||||
// Show apps from category
|
||||
if (selectedCategory === "All") {
|
||||
apps = AppSearchService.applications || [];
|
||||
} else {
|
||||
@@ -58,7 +50,6 @@ Item {
|
||||
apps = categoryApps.slice(0, maxResults);
|
||||
}
|
||||
} else {
|
||||
// Search with category filter
|
||||
if (selectedCategory === "All") {
|
||||
apps = AppSearchService.searchApplications(searchQuery);
|
||||
} else {
|
||||
@@ -88,7 +79,6 @@ Item {
|
||||
return (a.name || "").localeCompare(b.name || "");
|
||||
});
|
||||
|
||||
// Convert to model format and populate
|
||||
apps.forEach((app) => {
|
||||
if (app)
|
||||
filteredModel.append({
|
||||
@@ -103,7 +93,6 @@ Item {
|
||||
});
|
||||
}
|
||||
|
||||
// Keyboard navigation functions
|
||||
function selectNext() {
|
||||
if (filteredModel.count > 0) {
|
||||
keyboardNavigationActive = true;
|
||||
@@ -142,7 +131,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// App launching
|
||||
function launchSelected() {
|
||||
if (filteredModel.count > 0 && selectedIndex >= 0 && selectedIndex < filteredModel.count) {
|
||||
var selectedApp = filteredModel.get(selectedIndex);
|
||||
@@ -151,28 +139,24 @@ Item {
|
||||
}
|
||||
|
||||
function launchApp(appData) {
|
||||
if (!appData) {
|
||||
console.warn("AppLauncher: No app data provided");
|
||||
if (!appData)
|
||||
return ;
|
||||
}
|
||||
|
||||
appData.desktopEntry.execute();
|
||||
appLaunched(appData);
|
||||
Prefs.addAppUsage(appData.desktopEntry);
|
||||
}
|
||||
|
||||
// Category management
|
||||
function setCategory(category) {
|
||||
selectedCategory = category;
|
||||
categorySelected(category);
|
||||
}
|
||||
|
||||
// View mode management
|
||||
function setViewMode(mode) {
|
||||
viewMode = mode;
|
||||
viewModeSelected(mode);
|
||||
}
|
||||
|
||||
// Watch for changes
|
||||
onSearchQueryChanged: {
|
||||
if (debounceSearch)
|
||||
searchDebounceTimer.restart();
|
||||
@@ -182,7 +166,6 @@ Item {
|
||||
onSelectedCategoryChanged: updateFilteredModel()
|
||||
onAppUsageRankingChanged: updateFilteredModel()
|
||||
on_WatchApplicationsChanged: updateFilteredModel()
|
||||
// Initialize
|
||||
Component.onCompleted: {
|
||||
updateFilteredModel();
|
||||
}
|
||||
@@ -191,7 +174,6 @@ Item {
|
||||
id: filteredModel
|
||||
}
|
||||
|
||||
// Search debouncing
|
||||
Timer {
|
||||
id: searchDebounceTimer
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ Item {
|
||||
|
||||
height: compact ? 36 : (72 + Theme.spacingS) // Single row vs two rows
|
||||
|
||||
// Compact single-row layout (for SpotlightModal style)
|
||||
Row {
|
||||
visible: compact
|
||||
width: parent.width
|
||||
@@ -55,13 +54,11 @@ Item {
|
||||
|
||||
}
|
||||
|
||||
// Two-row layout (for SpotlightModal organized style)
|
||||
Column {
|
||||
visible: !compact
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Top row: All, Development, Graphics, Games (4 items)
|
||||
Row {
|
||||
property var topRowCategories: ["All", "Development", "Graphics", "Games"]
|
||||
|
||||
@@ -105,7 +102,6 @@ Item {
|
||||
|
||||
}
|
||||
|
||||
// Bottom row: Internet, Media, Office, Settings, System (5 items)
|
||||
Row {
|
||||
property var bottomRowCategories: ["Internet", "Media", "Office", "Settings", "System"]
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ Column {
|
||||
if (!CalendarService || !CalendarService.khalAvailable)
|
||||
return ;
|
||||
|
||||
// Calculate date range with padding
|
||||
let firstDay = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1);
|
||||
let dayOfWeek = firstDay.getDay();
|
||||
let startDate = new Date(firstDay);
|
||||
@@ -27,7 +26,6 @@ Column {
|
||||
}
|
||||
|
||||
spacing: Theme.spacingM
|
||||
// Load events when display date changes
|
||||
onDisplayDateChanged: {
|
||||
loadEventsForMonth();
|
||||
}
|
||||
@@ -35,7 +33,6 @@ Column {
|
||||
loadEventsForMonth();
|
||||
}
|
||||
|
||||
// Load events when calendar service becomes available
|
||||
Connections {
|
||||
function onKhalAvailableChanged() {
|
||||
if (CalendarService && CalendarService.khalAvailable)
|
||||
@@ -47,7 +44,6 @@ Column {
|
||||
enabled: CalendarService !== null
|
||||
}
|
||||
|
||||
// Month navigation header
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 40
|
||||
@@ -121,7 +117,6 @@ Column {
|
||||
|
||||
}
|
||||
|
||||
// Days of week header
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 32
|
||||
@@ -148,7 +143,6 @@ Column {
|
||||
|
||||
}
|
||||
|
||||
// Calendar grid
|
||||
Grid {
|
||||
property date firstDay: {
|
||||
let date = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1);
|
||||
@@ -196,7 +190,6 @@ Column {
|
||||
font.weight: isToday || isSelected ? Font.Medium : Font.Normal
|
||||
}
|
||||
|
||||
// Event indicator - bottom fill effect
|
||||
Rectangle {
|
||||
id: eventIndicator
|
||||
|
||||
|
||||
@@ -21,10 +21,7 @@ PanelWindow {
|
||||
if (calendarVisible) {
|
||||
internalVisible = true;
|
||||
Qt.callLater(() => {
|
||||
// This ensures opacity changes after window is visible
|
||||
internalVisible = true;
|
||||
// Force re-trigger if needed
|
||||
// Ensure events are loaded for current display month
|
||||
calendarGrid.loadEventsForMonth();
|
||||
});
|
||||
} else {
|
||||
@@ -51,8 +48,6 @@ PanelWindow {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// Animation finished, now we can safely resize
|
||||
|
||||
id: mainContainer
|
||||
|
||||
readonly property real targetWidth: Math.min(Screen.width * 0.9, 600)
|
||||
@@ -67,21 +62,16 @@ PanelWindow {
|
||||
|
||||
function calculateHeight() {
|
||||
let contentHeight = Theme.spacingM * 2; // margins
|
||||
// Main row with widgets and calendar
|
||||
let widgetHeight = 160;
|
||||
// Media widget always present
|
||||
widgetHeight += 140 + Theme.spacingM;
|
||||
// Weather widget always present
|
||||
let calendarHeight = 300;
|
||||
let mainRowHeight = Math.max(widgetHeight, calendarHeight);
|
||||
contentHeight += mainRowHeight + Theme.spacingM;
|
||||
// Add events widget height - use calculated height instead of actual
|
||||
if (CalendarService && CalendarService.khalAvailable) {
|
||||
let hasEvents = events.selectedDateEvents && events.selectedDateEvents.length > 0;
|
||||
let eventsHeight = hasEvents ? Math.min(300, 80 + events.selectedDateEvents.length * 60) : 120;
|
||||
contentHeight += eventsHeight;
|
||||
} else {
|
||||
// When no khal, reduce bottom margin to match top
|
||||
contentHeight -= Theme.spacingM;
|
||||
}
|
||||
return Math.min(contentHeight, parent.height * 0.9);
|
||||
@@ -98,7 +88,6 @@ PanelWindow {
|
||||
scale: calendarVisible ? 1 : 0.9
|
||||
x: (Screen.width - targetWidth) / 2
|
||||
y: Theme.barHeight + 4
|
||||
// Only resize after animation is complete
|
||||
onOpacityChanged: {
|
||||
if (opacity === 1)
|
||||
Qt.callLater(() => {
|
||||
@@ -165,7 +154,6 @@ PanelWindow {
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Main row with widgets and calendar - improved spacing and proportions
|
||||
Row {
|
||||
width: parent.width
|
||||
height: {
|
||||
@@ -176,7 +164,6 @@ PanelWindow {
|
||||
}
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Left section for widgets - improved visual hierarchy
|
||||
Column {
|
||||
id: leftWidgets
|
||||
|
||||
@@ -200,7 +187,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Right section for calendar - enhanced container
|
||||
Rectangle {
|
||||
width: leftWidgets.hasAnyWidgets ? parent.width * 0.55 - Theme.spacingM : parent.width
|
||||
height: parent.height
|
||||
@@ -263,7 +249,6 @@ PanelWindow {
|
||||
z: -1
|
||||
enabled: calendarVisible
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the main container
|
||||
var localPos = mapToItem(mainContainer, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0 || localPos.y > mainContainer.height)
|
||||
calendarVisible = false;
|
||||
|
||||
@@ -5,7 +5,6 @@ import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
// Events widget for selected date - Material Design 3 style
|
||||
Rectangle {
|
||||
id: events
|
||||
|
||||
@@ -17,7 +16,6 @@ Rectangle {
|
||||
function updateSelectedDateEvents() {
|
||||
if (CalendarService && CalendarService.khalAvailable) {
|
||||
let events = CalendarService.getEventsForDate(selectedDate);
|
||||
console.log("Events: Updating events for", Qt.formatDate(selectedDate, "yyyy-MM-dd"), "found", events.length, "events");
|
||||
selectedDateEvents = events;
|
||||
} else {
|
||||
selectedDateEvents = [];
|
||||
@@ -25,7 +23,6 @@ Rectangle {
|
||||
}
|
||||
|
||||
onSelectedDateEventsChanged: {
|
||||
console.log("Events: selectedDateEvents changed, count:", selectedDateEvents.length);
|
||||
eventsList.model = selectedDateEvents;
|
||||
}
|
||||
width: parent.width
|
||||
@@ -35,7 +32,6 @@ Rectangle {
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
visible: shouldShow
|
||||
// Material elevation shadow
|
||||
layer.enabled: true
|
||||
Component.onCompleted: {
|
||||
updateSelectedDateEvents();
|
||||
@@ -44,7 +40,6 @@ Rectangle {
|
||||
updateSelectedDateEvents();
|
||||
}
|
||||
|
||||
// Update events when selected date or events change
|
||||
Connections {
|
||||
function onEventsByDateChanged() {
|
||||
updateSelectedDateEvents();
|
||||
@@ -58,7 +53,6 @@ Rectangle {
|
||||
enabled: CalendarService !== null
|
||||
}
|
||||
|
||||
// Header - always visible when widget is shown
|
||||
Row {
|
||||
id: headerRow
|
||||
|
||||
@@ -85,7 +79,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// No events placeholder - centered in entire widget (not just content area)
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
@@ -108,7 +101,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Events list - positioned below header when there are events
|
||||
ListView {
|
||||
id: eventsList
|
||||
|
||||
@@ -157,7 +149,6 @@ Rectangle {
|
||||
}
|
||||
border.width: 1
|
||||
|
||||
// Event indicator strip
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: parent.height - 8
|
||||
@@ -270,7 +261,7 @@ Rectangle {
|
||||
onClicked: {
|
||||
if (modelData.url && modelData.url !== "") {
|
||||
if (Qt.openUrlExternally(modelData.url) === false)
|
||||
console.warn("Couldn't open", modelData.url);
|
||||
console.warn("Failed to open URL: " + modelData.url);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ Rectangle {
|
||||
property string lastValidArtUrl: ""
|
||||
property real currentPosition: 0
|
||||
|
||||
// Simple progress ratio calculation
|
||||
function ratio() {
|
||||
return activePlayer && activePlayer.length > 0 ? currentPosition / activePlayer.length : 0;
|
||||
}
|
||||
@@ -41,26 +40,22 @@ Rectangle {
|
||||
|
||||
interval: 2000
|
||||
running: {
|
||||
// Run when no active player (for cache clearing) OR when playing (for position updates)
|
||||
return (!activePlayer) || (activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing && activePlayer.length > 0 && !progressMouseArea.isSeeking);
|
||||
}
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (!activePlayer) {
|
||||
// Clear cache when no player
|
||||
lastValidTitle = "";
|
||||
lastValidArtist = "";
|
||||
lastValidAlbum = "";
|
||||
lastValidArtUrl = "";
|
||||
stop(); // Stop after clearing cache
|
||||
} else if (activePlayer.playbackState === MprisPlaybackState.Playing && !progressMouseArea.isSeeking) {
|
||||
// Update position when playing
|
||||
currentPosition = activePlayer.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Backend events
|
||||
Connections {
|
||||
function onPositionChanged() {
|
||||
if (!progressMouseArea.isSeeking)
|
||||
@@ -83,7 +78,6 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingS
|
||||
|
||||
// Placeholder when no media - centered in entire widget
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
@@ -105,19 +99,16 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Active content in a column
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: Theme.spacingS
|
||||
visible: activePlayer && activePlayer.trackTitle !== "" || lastValidTitle !== ""
|
||||
|
||||
// Normal media info when playing
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 60
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Album Art
|
||||
Rectangle {
|
||||
width: 60
|
||||
height: 60
|
||||
@@ -161,7 +152,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Track Info
|
||||
Column {
|
||||
width: parent.width - 60 - Theme.spacingM
|
||||
height: parent.height
|
||||
@@ -218,7 +208,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Progress bar
|
||||
Item {
|
||||
id: progressBarContainer
|
||||
|
||||
@@ -252,7 +241,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Drag handle
|
||||
Rectangle {
|
||||
id: progressHandle
|
||||
|
||||
@@ -318,7 +306,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Global mouse area for drag tracking
|
||||
MouseArea {
|
||||
id: progressGlobalMouseArea
|
||||
|
||||
@@ -345,7 +332,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Control buttons - always visible
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 32
|
||||
@@ -356,7 +342,6 @@ Rectangle {
|
||||
spacing: Theme.spacingM
|
||||
height: parent.height
|
||||
|
||||
// Previous button
|
||||
Rectangle {
|
||||
width: 28
|
||||
height: 28
|
||||
@@ -380,7 +365,6 @@ Rectangle {
|
||||
if (!activePlayer)
|
||||
return ;
|
||||
|
||||
// >8 s → jump to start, otherwise previous track
|
||||
if (currentPosition > 8 && activePlayer.canSeek) {
|
||||
activePlayer.position = 0;
|
||||
currentPosition = 0;
|
||||
@@ -392,7 +376,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Play/Pause button
|
||||
Rectangle {
|
||||
width: 32
|
||||
height: 32
|
||||
@@ -415,7 +398,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Next button
|
||||
Rectangle {
|
||||
width: 28
|
||||
height: 28
|
||||
|
||||
@@ -20,7 +20,6 @@ Rectangle {
|
||||
service: WeatherService
|
||||
}
|
||||
|
||||
// Placeholder when no weather - centered in entire widget
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
@@ -42,14 +41,12 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Weather content when available - original Column structure
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
visible: WeatherService.weather.available && WeatherService.weather.temp !== 0
|
||||
|
||||
// Weather header info
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 60
|
||||
@@ -58,7 +55,6 @@ Rectangle {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingL
|
||||
|
||||
// Weather icon
|
||||
DankIcon {
|
||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||
size: Theme.iconSize + 8
|
||||
@@ -103,7 +99,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Weather details grid
|
||||
Grid {
|
||||
columns: 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
@@ -23,13 +23,10 @@ PanelWindow {
|
||||
|
||||
visible: controlCenterVisible
|
||||
onVisibleChanged: {
|
||||
// Enable/disable WiFi auto-refresh based on control center visibility
|
||||
NetworkService.autoRefreshEnabled = visible && NetworkService.wifiEnabled;
|
||||
// Stop bluetooth scanning when control center is closed
|
||||
if (!visible && BluetoothService.adapter && BluetoothService.adapter.discovering)
|
||||
BluetoothService.adapter.discovering = false;
|
||||
|
||||
// Refresh uptime when opened
|
||||
if (visible && UserInfoService)
|
||||
UserInfoService.getUptime();
|
||||
|
||||
@@ -59,7 +56,6 @@ PanelWindow {
|
||||
height: root.powerOptionsExpanded ? 570 : 500
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||
// GPU-accelerated scale + opacity animation
|
||||
opacity: controlCenterVisible ? 1 : 0
|
||||
scale: controlCenterVisible ? 1 : 0.9
|
||||
|
||||
@@ -86,7 +82,6 @@ PanelWindow {
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
// Remove layer rendering for better performance
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
|
||||
@@ -95,7 +90,6 @@ PanelWindow {
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Elegant User Header
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
@@ -115,7 +109,6 @@ PanelWindow {
|
||||
anchors.rightMargin: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
// Profile Picture Container
|
||||
Item {
|
||||
id: avatarContainer
|
||||
|
||||
@@ -124,7 +117,6 @@ PanelWindow {
|
||||
width: 64
|
||||
height: 64
|
||||
|
||||
// This rectangle provides the themed ring via its border.
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
@@ -134,7 +126,6 @@ PanelWindow {
|
||||
visible: parent.hasImage
|
||||
}
|
||||
|
||||
// Hidden Image loader. Its only purpose is to load the texture.
|
||||
Image {
|
||||
id: profileImageLoader
|
||||
|
||||
@@ -183,7 +174,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Fallback for when there is no image.
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
@@ -199,7 +189,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Error icon for when the image fails to load.
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "warning"
|
||||
@@ -210,7 +199,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// User Info Text
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingXS
|
||||
@@ -233,14 +221,12 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Action Buttons - Lock, Power and Settings
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.rightMargin: Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Lock Button
|
||||
DankActionButton {
|
||||
buttonSize: 40
|
||||
iconName: "lock"
|
||||
@@ -254,7 +240,6 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Power Button
|
||||
Rectangle {
|
||||
width: 40
|
||||
height: 40
|
||||
@@ -278,7 +263,6 @@ PanelWindow {
|
||||
color: powerButton.containsMouse || root.powerOptionsExpanded ? Theme.error : Theme.surfaceText
|
||||
|
||||
Behavior on name {
|
||||
// Smooth icon transition
|
||||
SequentialAnimation {
|
||||
NumberAnimation {
|
||||
target: dankIcon
|
||||
@@ -330,7 +314,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Settings Button
|
||||
DankActionButton {
|
||||
buttonSize: 40
|
||||
iconName: "settings"
|
||||
@@ -348,7 +331,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Animated Collapsible Power Options (optimized)
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: root.powerOptionsExpanded ? 60 : 0
|
||||
@@ -364,7 +346,6 @@ PanelWindow {
|
||||
spacing: Theme.spacingL
|
||||
visible: root.powerOptionsExpanded
|
||||
|
||||
// Logout
|
||||
Rectangle {
|
||||
width: 100
|
||||
height: 34
|
||||
@@ -414,7 +395,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Reboot
|
||||
Rectangle {
|
||||
width: 100
|
||||
height: 34
|
||||
@@ -464,7 +444,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Suspend
|
||||
Rectangle {
|
||||
width: 100
|
||||
height: 34
|
||||
@@ -514,7 +493,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
Rectangle {
|
||||
width: 100
|
||||
height: 34
|
||||
@@ -566,7 +544,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Single coordinated animation for power options
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
@@ -689,7 +666,6 @@ PanelWindow {
|
||||
anchors.margins: Theme.spacingS
|
||||
visible: root.currentTab === "display"
|
||||
spacing: Theme.spacingL
|
||||
// Brightness Control
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
@@ -765,7 +741,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Power menu height animation
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration // Faster for height changes
|
||||
@@ -778,12 +753,10 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Click outside to close
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the content loader
|
||||
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
|
||||
controlCenterVisible = false;
|
||||
|
||||
@@ -19,7 +19,7 @@ ScrollView {
|
||||
interval: BrightnessService.ddcAvailable ? 500 : 50 // 500ms for slow DDC (i2c), 50ms for fast laptop backlight
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
console.log("Debounce timer fired, setting brightness to:", pendingValue);
|
||||
|
||||
BrightnessService.setBrightness(pendingValue);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ ScrollView {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
// Brightness Control
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
@@ -49,12 +48,12 @@ ScrollView {
|
||||
rightIcon: "brightness_high"
|
||||
enabled: BrightnessService.brightnessAvailable
|
||||
onSliderValueChanged: function(newValue) {
|
||||
console.log("Slider changed to:", newValue);
|
||||
|
||||
brightnessDebounceTimer.pendingValue = newValue;
|
||||
brightnessDebounceTimer.restart();
|
||||
}
|
||||
onSliderDragFinished: function(finalValue) {
|
||||
console.log("Drag finished, immediate set:", finalValue);
|
||||
|
||||
brightnessDebounceTimer.stop();
|
||||
BrightnessService.setBrightness(finalValue);
|
||||
}
|
||||
@@ -70,7 +69,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Display settings
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
@@ -82,12 +80,10 @@ ScrollView {
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
// Mode toggles row (Night Mode + Light/Dark Mode)
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Night mode toggle
|
||||
Rectangle {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: 80
|
||||
@@ -125,11 +121,9 @@ ScrollView {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (Prefs.nightModeEnabled) {
|
||||
// Disable night mode - kill any running color temperature processes
|
||||
nightModeDisableProcess.running = true;
|
||||
Prefs.setNightModeEnabled(false);
|
||||
} else {
|
||||
// Enable night mode using wlsunset or redshift
|
||||
nightModeEnableProcess.running = true;
|
||||
Prefs.setNightModeEnabled(true);
|
||||
}
|
||||
@@ -138,7 +132,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Light/Dark mode toggle
|
||||
Rectangle {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: 80
|
||||
@@ -195,7 +188,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Night mode processes
|
||||
Process {
|
||||
id: nightModeEnableProcess
|
||||
|
||||
@@ -203,7 +195,7 @@ ScrollView {
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
console.warn("Failed to enable night mode");
|
||||
|
||||
Prefs.setNightModeEnabled(false);
|
||||
}
|
||||
}
|
||||
@@ -216,7 +208,7 @@ ScrollView {
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0)
|
||||
console.warn("Failed to disable night mode");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Loading spinner for preference changes
|
||||
DankIcon {
|
||||
id: ethernetLoadingSpinner
|
||||
|
||||
@@ -86,7 +85,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Ethernet toggle switch (matching WiFi style)
|
||||
DankToggle {
|
||||
id: ethernetToggle
|
||||
|
||||
@@ -100,7 +98,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// MouseArea for network preference (excluding toggle area)
|
||||
MouseArea {
|
||||
id: ethernetPreferenceArea
|
||||
|
||||
@@ -111,7 +108,7 @@ Rectangle {
|
||||
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet" && !NetworkService.changingNetworkPreference
|
||||
onClicked: {
|
||||
if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) {
|
||||
console.log("Ethernet card clicked for preference");
|
||||
|
||||
if (NetworkService.networkStatus !== "ethernet")
|
||||
NetworkService.setNetworkPreference("ethernet");
|
||||
else
|
||||
|
||||
@@ -100,7 +100,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Loading spinner for preference changes
|
||||
DankIcon {
|
||||
id: wifiLoadingSpinner
|
||||
|
||||
@@ -125,7 +124,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// WiFi toggle switch
|
||||
DankToggle {
|
||||
id: wifiToggle
|
||||
|
||||
@@ -137,7 +135,6 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
if (NetworkService.wifiEnabled) {
|
||||
// When turning WiFi off, clear all cached WiFi data
|
||||
NetworkService.currentWifiSSID = "";
|
||||
NetworkService.wifiSignalStrength = "excellent";
|
||||
NetworkService.wifiNetworks = [];
|
||||
@@ -154,7 +151,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// MouseArea for network preference (excluding toggle area)
|
||||
MouseArea {
|
||||
id: wifiPreferenceArea
|
||||
|
||||
@@ -165,7 +161,7 @@ Rectangle {
|
||||
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi" && !NetworkService.changingNetworkPreference
|
||||
onClicked: {
|
||||
if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) {
|
||||
console.log("WiFi card clicked for preference");
|
||||
|
||||
if (NetworkService.networkStatus !== "wifi")
|
||||
NetworkService.setNetworkPreference("wifi");
|
||||
else
|
||||
|
||||
@@ -57,7 +57,6 @@ Rectangle {
|
||||
visible = false;
|
||||
}
|
||||
|
||||
// Drop shadow
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 4
|
||||
@@ -76,7 +75,6 @@ Rectangle {
|
||||
anchors.margins: Theme.spacingS
|
||||
spacing: 1
|
||||
|
||||
// Connect/Disconnect option
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32
|
||||
@@ -145,7 +143,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Separator
|
||||
Rectangle {
|
||||
width: parent.width - Theme.spacingS * 2
|
||||
height: 5
|
||||
@@ -161,7 +158,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Forget Network option (only for saved networks)
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32
|
||||
@@ -217,7 +213,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Network Info option
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32
|
||||
|
||||
@@ -37,7 +37,6 @@ Column {
|
||||
visible: NetworkService.wifiEnabled
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Available Networks Section with refresh button (spanning version)
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
@@ -55,7 +54,6 @@ Column {
|
||||
height: 1
|
||||
}
|
||||
|
||||
// WiFi refresh button (spanning version)
|
||||
Rectangle {
|
||||
width: 28
|
||||
height: 28
|
||||
@@ -99,7 +97,6 @@ Column {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (!NetworkService.isScanning) {
|
||||
// Immediate visual feedback
|
||||
refreshIconSpan.rotation += 30;
|
||||
NetworkService.scanWifi();
|
||||
}
|
||||
@@ -110,7 +107,6 @@ Column {
|
||||
|
||||
}
|
||||
|
||||
// Scrollable networks container
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: parent.height - 40
|
||||
@@ -143,7 +139,6 @@ Column {
|
||||
anchors.margins: Theme.spacingXS
|
||||
anchors.rightMargin: Theme.spacingM // Extra right margin for scrollbar
|
||||
|
||||
// Signal strength icon
|
||||
DankIcon {
|
||||
id: signalIcon2
|
||||
|
||||
@@ -154,7 +149,6 @@ Column {
|
||||
color: modelData.connected ? Theme.primary : Theme.surfaceText
|
||||
}
|
||||
|
||||
// Network info
|
||||
Column {
|
||||
anchors.left: signalIcon2.right
|
||||
anchors.leftMargin: Theme.spacingXS
|
||||
@@ -204,7 +198,6 @@ Column {
|
||||
|
||||
}
|
||||
|
||||
// Right side icons
|
||||
Row {
|
||||
id: rightIcons2
|
||||
|
||||
@@ -212,7 +205,6 @@ Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
// Lock icon (if secured)
|
||||
DankIcon {
|
||||
name: "lock"
|
||||
size: Theme.iconSize - 8
|
||||
@@ -221,7 +213,6 @@ Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
// Context menu button
|
||||
Rectangle {
|
||||
id: wifiMenuButton
|
||||
|
||||
|
||||
@@ -14,13 +14,11 @@ Item {
|
||||
property var wifiPasswordModalRef: wifiPasswordModal
|
||||
property var networkInfoModalRef: networkInfoModal
|
||||
|
||||
// Properly sorted WiFi networks with connected networks first
|
||||
property var sortedWifiNetworks: {
|
||||
if (!NetworkService.wifiAvailable || !NetworkService.wifiEnabled) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Explicitly reference both arrays to ensure reactivity
|
||||
var allNetworks = NetworkService.wifiNetworks;
|
||||
var savedNetworks = NetworkService.savedWifiNetworks;
|
||||
var currentSSID = NetworkService.currentWifiSSID;
|
||||
@@ -29,32 +27,25 @@ Item {
|
||||
|
||||
var networks = [...allNetworks];
|
||||
|
||||
// Update connected status, saved status and signal strength based on current state
|
||||
networks.forEach(function(network) {
|
||||
network.connected = (network.ssid === currentSSID);
|
||||
// Update saved status based on savedWifiNetworks
|
||||
network.saved = savedNetworks.some(function(saved) {
|
||||
return saved.ssid === network.ssid;
|
||||
});
|
||||
// Use current connection's signal strength for connected network
|
||||
if (network.connected && signalStrength) {
|
||||
network.signalStrength = signalStrength;
|
||||
}
|
||||
});
|
||||
|
||||
// Sort: connected networks first, then by signal strength
|
||||
networks.sort(function(a, b) {
|
||||
// Connected networks always come first
|
||||
if (a.connected && !b.connected) return -1;
|
||||
if (!a.connected && b.connected) return 1;
|
||||
// If both connected or both not connected, sort by signal strength
|
||||
return b.signal - a.signal;
|
||||
});
|
||||
|
||||
return networks;
|
||||
}
|
||||
|
||||
// Force refresh of sortedWifiNetworks when networks are updated
|
||||
property int forceRefresh: 0
|
||||
|
||||
Connections {
|
||||
@@ -64,13 +55,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-enable WiFi auto-refresh when network tab is visible
|
||||
Component.onCompleted: {
|
||||
NetworkService.addRef();
|
||||
NetworkService.autoRefreshEnabled = true;
|
||||
if (NetworkService.wifiEnabled)
|
||||
NetworkService.scanWifi();
|
||||
// Start smart monitoring
|
||||
wifiMonitorTimer.start();
|
||||
}
|
||||
|
||||
@@ -79,18 +68,15 @@ Item {
|
||||
NetworkService.autoRefreshEnabled = false;
|
||||
}
|
||||
|
||||
// Two-column layout for WiFi and Ethernet (WiFi on left, Ethernet on right)
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// WiFi Column (left side)
|
||||
Column {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: parent.height
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// WiFi Content in Flickable
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: parent.height - 30
|
||||
@@ -106,7 +92,6 @@ Item {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Current WiFi connection status card
|
||||
WiFiCard {
|
||||
refreshTimer: refreshTimer
|
||||
}
|
||||
@@ -118,13 +103,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Ethernet Column (right side)
|
||||
Column {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: parent.height
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Ethernet Content in Flickable
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: parent.height - 30
|
||||
@@ -140,7 +123,6 @@ Item {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Ethernet connection status card (matching WiFi height)
|
||||
EthernetCard {
|
||||
}
|
||||
}
|
||||
@@ -152,7 +134,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// WiFi disabled message spanning across both columns
|
||||
Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 100
|
||||
@@ -190,14 +171,12 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// WiFi networks spanning across both columns when WiFi is enabled
|
||||
WiFiNetworksList {
|
||||
wifiContextMenuWindow: wifiContextMenuWindow
|
||||
sortedWifiNetworks: networkTab.sortedWifiNetworks
|
||||
wifiPasswordModalRef: networkTab.wifiPasswordModalRef
|
||||
}
|
||||
|
||||
// Timer for refreshing network status after WiFi toggle
|
||||
Timer {
|
||||
id: refreshTimer
|
||||
interval: 2000
|
||||
@@ -212,18 +191,13 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-refresh when WiFi state changes
|
||||
Connections {
|
||||
target: NetworkService
|
||||
function onWifiEnabledChanged() {
|
||||
if (NetworkService.wifiEnabled && visible) {
|
||||
// When WiFi is enabled, scan and update info (only if tab is visible)
|
||||
// Add a small delay to ensure WiFi service is ready
|
||||
wifiScanDelayTimer.start();
|
||||
// Start monitoring when WiFi comes back on
|
||||
wifiMonitorTimer.start();
|
||||
} else {
|
||||
// When WiFi is disabled, clear all cached WiFi data
|
||||
NetworkService.currentWifiSSID = "";
|
||||
NetworkService.wifiSignalStrength = "excellent";
|
||||
NetworkService.wifiNetworks = [];
|
||||
@@ -232,13 +206,11 @@ Item {
|
||||
NetworkService.connectingSSID = "";
|
||||
NetworkService.isScanning = false;
|
||||
NetworkService.refreshNetworkStatus();
|
||||
// Stop monitoring when WiFi is off
|
||||
wifiMonitorTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delayed WiFi scan timer to ensure service is ready
|
||||
Timer {
|
||||
id: wifiScanDelayTimer
|
||||
interval: 1500
|
||||
@@ -249,14 +221,12 @@ Item {
|
||||
if (!NetworkService.isScanning) {
|
||||
NetworkService.scanWifi();
|
||||
} else {
|
||||
// If still scanning, try again in a bit
|
||||
wifiRetryTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retry timer for when WiFi is still scanning
|
||||
Timer {
|
||||
id: wifiRetryTimer
|
||||
interval: 2000
|
||||
@@ -271,7 +241,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Smart WiFi monitoring - only runs when tab visible and conditions met
|
||||
Timer {
|
||||
id: wifiMonitorTimer
|
||||
interval: 8000 // Check every 8 seconds
|
||||
@@ -279,21 +248,17 @@ Item {
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (!visible || !NetworkService.wifiEnabled) {
|
||||
// Stop monitoring when not needed
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Monitor connection changes and refresh networks when disconnected
|
||||
var shouldScan = false;
|
||||
var reason = "";
|
||||
|
||||
// Always scan if not connected to WiFi
|
||||
if (NetworkService.networkStatus !== "wifi") {
|
||||
shouldScan = true;
|
||||
reason = "not connected to WiFi";
|
||||
}
|
||||
// Also scan occasionally even when connected to keep networks fresh
|
||||
else if (NetworkService.wifiNetworks.length === 0) {
|
||||
shouldScan = true;
|
||||
reason = "no networks cached";
|
||||
@@ -305,7 +270,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Monitor tab visibility to start/stop smart monitoring
|
||||
onVisibleChanged: {
|
||||
if (visible && NetworkService.wifiEnabled) {
|
||||
wifiMonitorTimer.start();
|
||||
@@ -314,7 +278,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// WiFi Context Menu Window
|
||||
WiFiContextMenu {
|
||||
id: wifiContextMenuWindow
|
||||
parentItem: networkTab
|
||||
@@ -322,7 +285,6 @@ Item {
|
||||
networkInfoModalRef: networkTab.networkInfoModalRef
|
||||
}
|
||||
|
||||
// Background MouseArea to close the context menu
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
visible: wifiContextMenuWindow.visible
|
||||
@@ -336,7 +298,6 @@ Item {
|
||||
width: wifiContextMenuWindow.width
|
||||
height: wifiContextMenuWindow.height
|
||||
onClicked: {
|
||||
// Prevent clicks on menu from closing it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ PanelWindow {
|
||||
bottom: true
|
||||
}
|
||||
|
||||
// Click outside to dismiss overlay
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
@@ -51,9 +50,7 @@ PanelWindow {
|
||||
opacity: powerMenuVisible ? 1 : 0
|
||||
scale: powerMenuVisible ? 1 : 0.85
|
||||
|
||||
// Prevent click-through to background
|
||||
MouseArea {
|
||||
// Consume the click to prevent it from reaching the background
|
||||
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
@@ -65,7 +62,6 @@ PanelWindow {
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Header
|
||||
Row {
|
||||
width: parent.width
|
||||
|
||||
@@ -94,12 +90,10 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Power options
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Log Out
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
@@ -146,7 +140,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Suspend
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
@@ -193,7 +186,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Reboot
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
@@ -240,7 +232,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Power Off
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
|
||||
@@ -66,7 +66,7 @@ PanelWindow {
|
||||
onScreenYChanged: margins.top = Theme.barHeight + 4 + screenY
|
||||
onHasValidDataChanged: {
|
||||
if (!hasValidData && !exiting && !_isDestroying) {
|
||||
console.warn("NotificationPopup: Data became invalid, forcing exit");
|
||||
|
||||
forceExit();
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ PanelWindow {
|
||||
return enterX.restart();
|
||||
});
|
||||
} else {
|
||||
console.warn("NotificationPopup created with invalid data");
|
||||
|
||||
forceExit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ QtObject {
|
||||
property int baseNotificationHeight: 120
|
||||
property int maxTargetNotifications: 3
|
||||
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
||||
// Track destroying windows to prevent duplicate cleanup
|
||||
property var destroyingWindows: new Set()
|
||||
// Factory
|
||||
property Component popupComponent
|
||||
|
||||
popupComponent: Component {
|
||||
@@ -34,7 +32,6 @@ QtObject {
|
||||
target: NotificationService
|
||||
}
|
||||
|
||||
// Smart sweeper that only runs when needed
|
||||
property Timer sweeper
|
||||
|
||||
sweeper: Timer {
|
||||
@@ -48,24 +45,21 @@ QtObject {
|
||||
toRemove.push(p);
|
||||
continue;
|
||||
}
|
||||
// Check for various zombie conditions
|
||||
const isZombie = p.status === Component.Null || (!p.visible && !p.exiting) || (!p.notificationData && !p._isDestroying) || (!p.hasValidData && !p._isDestroying);
|
||||
if (isZombie) {
|
||||
console.warn("Sweeper found zombie window, cleaning up");
|
||||
|
||||
toRemove.push(p);
|
||||
// Try to force cleanup
|
||||
if (p.forceExit) {
|
||||
p.forceExit();
|
||||
} else if (p.destroy) {
|
||||
try {
|
||||
p.destroy();
|
||||
} catch (e) {
|
||||
console.warn("Error destroying zombie:", e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove all zombies from array
|
||||
if (toRemove.length > 0) {
|
||||
for (let zombie of toRemove) {
|
||||
const i = popupWindows.indexOf(zombie);
|
||||
@@ -74,7 +68,6 @@ QtObject {
|
||||
|
||||
}
|
||||
popupWindows = popupWindows.slice();
|
||||
// Recompact after cleanup
|
||||
const survivors = _active().sort((a, b) => {
|
||||
return a.screenY - b.screenY;
|
||||
});
|
||||
@@ -82,7 +75,6 @@ QtObject {
|
||||
survivors[k].screenY = topMargin + k * baseNotificationHeight;
|
||||
}
|
||||
}
|
||||
// Stop the timer if no windows remain
|
||||
if (popupWindows.length === 0)
|
||||
sweeper.stop();
|
||||
|
||||
@@ -91,7 +83,6 @@ QtObject {
|
||||
|
||||
function _hasWindowFor(w) {
|
||||
return popupWindows.some((p) => {
|
||||
// More robust check for valid windows
|
||||
return p && p.notificationData === w && !p._isDestroying && p.status !== Component.Null;
|
||||
});
|
||||
}
|
||||
@@ -101,13 +92,11 @@ QtObject {
|
||||
}
|
||||
|
||||
function _sync(newWrappers) {
|
||||
// Add new notifications
|
||||
for (let w of newWrappers) {
|
||||
if (w && !_hasWindowFor(w))
|
||||
insertNewestAtTop(w);
|
||||
|
||||
}
|
||||
// Remove old notifications
|
||||
for (let p of popupWindows.slice()) {
|
||||
if (!_isValidWindow(p))
|
||||
continue;
|
||||
@@ -119,13 +108,11 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
// Insert newest at top
|
||||
function insertNewestAtTop(wrapper) {
|
||||
if (!wrapper) {
|
||||
console.warn("insertNewestAtTop: wrapper is null");
|
||||
|
||||
return ;
|
||||
}
|
||||
// Shift live, non-exiting windows down *now*
|
||||
for (let p of popupWindows) {
|
||||
if (!_isValidWindow(p))
|
||||
continue;
|
||||
@@ -135,7 +122,6 @@ QtObject {
|
||||
|
||||
p.screenY = p.screenY + baseNotificationHeight;
|
||||
}
|
||||
// Create the new top window at fixed Y
|
||||
const notificationId = wrapper && wrapper.notification ? wrapper.notification.id : "";
|
||||
const win = popupComponent.createObject(null, {
|
||||
"notificationData": wrapper,
|
||||
@@ -144,24 +130,21 @@ QtObject {
|
||||
"screen": manager.modelData
|
||||
});
|
||||
if (!win) {
|
||||
console.warn("Popup create failed");
|
||||
|
||||
return ;
|
||||
}
|
||||
// Validate the window was created properly
|
||||
if (!win.hasValidData) {
|
||||
console.warn("Popup created with invalid data, destroying");
|
||||
|
||||
win.destroy();
|
||||
return ;
|
||||
}
|
||||
popupWindows.push(win);
|
||||
// Start sweeper if it's not running
|
||||
if (!sweeper.running)
|
||||
sweeper.start();
|
||||
|
||||
_maybeStartOverflow();
|
||||
}
|
||||
|
||||
// Overflow: keep one extra (slot #4), then ask bottom to exit gracefully
|
||||
function _active() {
|
||||
return popupWindows.filter((p) => {
|
||||
return _isValidWindow(p) && p.notificationData && p.notificationData.popup && !p.exiting;
|
||||
@@ -186,55 +169,46 @@ QtObject {
|
||||
|
||||
const b = _bottom();
|
||||
if (b && !b.exiting) {
|
||||
// Tell the popup to animate out (don't destroy here)
|
||||
b.notificationData.removedByLimit = true;
|
||||
b.notificationData.popup = false;
|
||||
}
|
||||
}
|
||||
|
||||
// After entrance, you may kick overflow (optional)
|
||||
function _onPopupEntered(p) {
|
||||
if (_isValidWindow(p))
|
||||
_maybeStartOverflow();
|
||||
|
||||
}
|
||||
|
||||
// Primary cleanup path (after the popup finishes its exit)
|
||||
function _onPopupExitFinished(p) {
|
||||
if (!p)
|
||||
return ;
|
||||
|
||||
// Prevent duplicate cleanup
|
||||
const windowId = p.toString();
|
||||
if (destroyingWindows.has(windowId))
|
||||
return ;
|
||||
|
||||
destroyingWindows.add(windowId);
|
||||
// Remove from popupWindows
|
||||
const i = popupWindows.indexOf(p);
|
||||
if (i !== -1) {
|
||||
popupWindows.splice(i, 1);
|
||||
popupWindows = popupWindows.slice();
|
||||
}
|
||||
// Release the wrapper
|
||||
if (NotificationService.releaseWrapper && p.notificationData)
|
||||
NotificationService.releaseWrapper(p.notificationData);
|
||||
|
||||
// Schedule destruction
|
||||
Qt.callLater(() => {
|
||||
if (p && p.destroy) {
|
||||
try {
|
||||
p.destroy();
|
||||
} catch (e) {
|
||||
console.warn("Error destroying popup:", e);
|
||||
|
||||
}
|
||||
}
|
||||
// Clean up tracking after a delay
|
||||
Qt.callLater(() => {
|
||||
destroyingWindows.delete(windowId);
|
||||
});
|
||||
});
|
||||
// Compact survivors (only live, non-exiting)
|
||||
const survivors = _active().sort((a, b) => {
|
||||
return a.screenY - b.screenY;
|
||||
});
|
||||
@@ -244,7 +218,6 @@ QtObject {
|
||||
_maybeStartOverflow();
|
||||
}
|
||||
|
||||
// Emergency cleanup function
|
||||
function cleanupAllWindows() {
|
||||
sweeper.stop();
|
||||
for (let p of popupWindows.slice()) {
|
||||
@@ -255,7 +228,7 @@ QtObject {
|
||||
else if (p.destroy)
|
||||
p.destroy();
|
||||
} catch (e) {
|
||||
console.warn("Error during emergency cleanup:", e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,7 +236,6 @@ QtObject {
|
||||
destroyingWindows.clear();
|
||||
}
|
||||
|
||||
// Watch for changes to popup windows array
|
||||
onPopupWindowsChanged: {
|
||||
if (popupWindows.length > 0 && !sweeper.running)
|
||||
sweeper.start();
|
||||
|
||||
@@ -19,7 +19,6 @@ PanelWindow {
|
||||
|
||||
function hide() {
|
||||
isVisible = false;
|
||||
// Close any open context menus
|
||||
if (processContextMenu.visible)
|
||||
processContextMenu.close();
|
||||
|
||||
@@ -58,7 +57,6 @@ PanelWindow {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the content loader
|
||||
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
|
||||
processListPopout.hide();
|
||||
@@ -78,7 +76,6 @@ PanelWindow {
|
||||
height: targetHeight
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||
// GPU-accelerated scale + opacity animation
|
||||
opacity: processListPopout.isVisible ? 1 : 0
|
||||
scale: processListPopout.isVisible ? 1 : 0.9
|
||||
|
||||
@@ -108,7 +105,6 @@ PanelWindow {
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
clip: true
|
||||
// Remove layer rendering for better performance
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
|
||||
|
||||
@@ -294,7 +294,6 @@ Column {
|
||||
}
|
||||
onModelChanged: {
|
||||
if (model && model.length > 0 && !isUserScrolling && stableY > 40)
|
||||
// Preserve scroll position when model updates
|
||||
Qt.callLater(function() {
|
||||
contentY = stableY;
|
||||
});
|
||||
|
||||
@@ -20,7 +20,6 @@ ScrollView {
|
||||
topPadding: Theme.spacingL
|
||||
bottomPadding: Theme.spacingXL
|
||||
|
||||
// Display Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: displaySection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -91,7 +90,6 @@ ScrollView {
|
||||
popupWidthOffset: 100
|
||||
maxPopupHeight: 400
|
||||
options: {
|
||||
// Force refresh of icon themes to prevent stale data
|
||||
Prefs.detectAvailableIconThemes();
|
||||
return Prefs.availableIconThemes;
|
||||
}
|
||||
@@ -108,7 +106,6 @@ ScrollView {
|
||||
text: "Font Family"
|
||||
description: "Select system font family"
|
||||
currentValue: {
|
||||
// Always show the font name in parentheses for clarity
|
||||
if (Prefs.fontFamily === Prefs.defaultFontFamily)
|
||||
return "Default (" + Prefs.defaultFontFamily + ")";
|
||||
else
|
||||
@@ -122,19 +119,15 @@ ScrollView {
|
||||
var availableFonts = Qt.fontFamilies();
|
||||
var rootFamilies = [];
|
||||
var seenFamilies = new Set();
|
||||
// Filter to root family names by removing common weight/style suffixes
|
||||
for (var i = 0; i < availableFonts.length; i++) {
|
||||
var fontName = availableFonts[i];
|
||||
// Skip fonts beginning with . (like .AppleSystem)
|
||||
if (fontName.startsWith("."))
|
||||
continue;
|
||||
|
||||
// Skip the default font since we already added it as recommended
|
||||
if (fontName === Prefs.defaultFontFamily)
|
||||
continue;
|
||||
|
||||
var rootName = fontName.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").replace(/ (UI|Display|Text|Mono|Sans|Serif)$/i, function(match, suffix) {
|
||||
// Keep these suffixes as they're part of the family name
|
||||
return match;
|
||||
}).trim();
|
||||
if (!seenFamilies.has(rootName) && rootName !== "") {
|
||||
@@ -237,18 +230,14 @@ ScrollView {
|
||||
var availableFonts = Qt.fontFamilies();
|
||||
var monoFamilies = [];
|
||||
var seenFamilies = new Set();
|
||||
// Filter to likely monospace fonts
|
||||
for (var i = 0; i < availableFonts.length; i++) {
|
||||
var fontName = availableFonts[i];
|
||||
// Skip fonts beginning with .
|
||||
if (fontName.startsWith("."))
|
||||
continue;
|
||||
|
||||
// Skip the default mono font since we already added it as recommended
|
||||
if (fontName === Prefs.defaultMonoFontFamily)
|
||||
continue;
|
||||
|
||||
// Look for common monospace indicators
|
||||
var lowerName = fontName.toLowerCase();
|
||||
if (lowerName.includes("mono") || lowerName.includes("code") || lowerName.includes("console") || lowerName.includes("terminal") || lowerName.includes("courier") || lowerName.includes("dejavu sans mono") || lowerName.includes("jetbrains") || lowerName.includes("fira") || lowerName.includes("hack") || lowerName.includes("source code") || lowerName.includes("ubuntu mono") || lowerName.includes("cascadia")) {
|
||||
var rootName = fontName.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").trim();
|
||||
@@ -272,7 +261,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Transparency Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: transparencySection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -391,7 +379,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Theme Picker Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: themeSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -458,12 +445,10 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Theme Grid
|
||||
Column {
|
||||
spacing: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
// First row - Blue, Deep Blue, Purple, Green, Orange
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -480,7 +465,6 @@ ScrollView {
|
||||
border.width: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 2 : 1
|
||||
scale: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 1.1 : 1
|
||||
|
||||
// Theme name tooltip
|
||||
Rectangle {
|
||||
width: nameText.contentWidth + Theme.spacingS * 2
|
||||
height: nameText.contentHeight + Theme.spacingXS * 2
|
||||
@@ -537,7 +521,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Second row - Red, Cyan, Pink, Amber, Coral
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -557,7 +540,6 @@ ScrollView {
|
||||
visible: themeIndex < Theme.themes.length
|
||||
scale: Theme.currentThemeIndex === themeIndex ? 1.1 : 1
|
||||
|
||||
// Theme name tooltip
|
||||
Rectangle {
|
||||
width: nameText2.contentWidth + Theme.spacingS * 2
|
||||
height: nameText2.contentHeight + Theme.spacingXS * 2
|
||||
@@ -616,13 +598,11 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Spacer
|
||||
Item {
|
||||
width: 1
|
||||
height: Theme.spacingM
|
||||
}
|
||||
|
||||
// Auto theme button
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
@@ -704,7 +684,6 @@ ScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
// Tooltip for Auto button
|
||||
Rectangle {
|
||||
width: autoTooltipText.contentWidth + Theme.spacingM * 2
|
||||
height: autoTooltipText.contentHeight + Theme.spacingS * 2
|
||||
@@ -768,7 +747,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// System App Theming Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: systemThemingSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -840,17 +818,15 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Night mode processes
|
||||
Process {
|
||||
id: nightModeEnableProcess
|
||||
|
||||
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
console.warn("Failed to enable night mode");
|
||||
Prefs.setNightModeEnabled(false);
|
||||
}
|
||||
if (exitCode !== 0)
|
||||
Prefs.setNightModeEnabled(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,7 +837,7 @@ ScrollView {
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0)
|
||||
console.warn("Failed to disable night mode");
|
||||
Prefs.setNightModeEnabled(false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ ScrollView {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
// Profile Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: profileSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -63,7 +62,6 @@ ScrollView {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
// Circular profile image preview
|
||||
Item {
|
||||
id: avatarContainer
|
||||
|
||||
@@ -264,7 +262,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Wallpaper Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: wallpaperSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -305,7 +302,6 @@ ScrollView {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
// Wallpaper Preview
|
||||
StyledRect {
|
||||
width: 160
|
||||
height: 90
|
||||
@@ -463,7 +459,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Dynamic Theming Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2
|
||||
|
||||
@@ -22,7 +22,6 @@ Column {
|
||||
|
||||
}
|
||||
|
||||
// Section header
|
||||
MouseArea {
|
||||
width: parent.width
|
||||
height: headerRow.height
|
||||
@@ -85,7 +84,6 @@ Column {
|
||||
|
||||
}
|
||||
|
||||
// Divider
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
@@ -93,7 +91,6 @@ Column {
|
||||
visible: expanded || !collapsible
|
||||
}
|
||||
|
||||
// Content
|
||||
Loader {
|
||||
id: contentLoader
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ ScrollView {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
// Time Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: timeSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -66,7 +65,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Weather Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: weatherSection.implicitHeight + Theme.spacingL * 2
|
||||
|
||||
@@ -91,7 +91,6 @@ ScrollView {
|
||||
"icon": "remove",
|
||||
"enabled": true
|
||||
}]
|
||||
// Default widget configurations for each section (with enabled states)
|
||||
property var defaultLeftWidgets: [{
|
||||
"id": "launcherButton",
|
||||
"enabled": true
|
||||
@@ -295,7 +294,6 @@ ScrollView {
|
||||
if (!Prefs.topBarRightWidgets || Prefs.topBarRightWidgets.length === 0)
|
||||
Prefs.setTopBarRightWidgets(defaultRightWidgets);
|
||||
|
||||
// Ensure existing spacers have default sizes
|
||||
["left", "center", "right"].forEach((sectionId) => {
|
||||
var widgets = [];
|
||||
if (sectionId === "left")
|
||||
@@ -334,7 +332,6 @@ ScrollView {
|
||||
topPadding: Theme.spacingL
|
||||
bottomPadding: Theme.spacingXL
|
||||
|
||||
// Header section
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
@@ -446,12 +443,10 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Widget sections
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
// Left Section
|
||||
DankSections {
|
||||
width: parent.width
|
||||
title: "Left Section"
|
||||
@@ -478,7 +473,6 @@ ScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
// Center Section
|
||||
DankSections {
|
||||
width: parent.width
|
||||
title: "Center Section"
|
||||
@@ -505,7 +499,6 @@ ScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
// Right Section
|
||||
DankSections {
|
||||
width: parent.width
|
||||
title: "Right Section"
|
||||
@@ -534,7 +527,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Workspace Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: workspaceSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -597,7 +589,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Tooltip for reset button (positioned above the button)
|
||||
Rectangle {
|
||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||
height: tooltipText.contentHeight + Theme.spacingS * 2
|
||||
@@ -630,7 +621,6 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
// Widget selection popup
|
||||
DankWidgetSelectionPopup {
|
||||
id: widgetSelectionPopup
|
||||
|
||||
|
||||
@@ -130,7 +130,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Makes the background transparent to mouse events
|
||||
mask: Region {
|
||||
item: toast
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ Item {
|
||||
interval: 256
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
// Generate fake audio levels when cava is unavailable
|
||||
CavaService.values = [Math.random() * 40 + 10, Math.random() * 60 + 20, Math.random() * 50 + 15, Math.random() * 35 + 20, Math.random() * 45 + 15, Math.random() * 55 + 25];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Tooltip on hover
|
||||
Rectangle {
|
||||
id: batteryTooltip
|
||||
|
||||
|
||||
@@ -46,11 +46,9 @@ PanelWindow {
|
||||
bottom: true
|
||||
}
|
||||
|
||||
// Click outside to dismiss overlay
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the content loader
|
||||
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
|
||||
batteryPopupVisible = false;
|
||||
@@ -70,7 +68,6 @@ PanelWindow {
|
||||
height: targetHeight
|
||||
x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||
y: Theme.barHeight + Theme.spacingS
|
||||
// GPU-accelerated scale + opacity animation
|
||||
opacity: batteryPopupVisible ? 1 : 0
|
||||
scale: batteryPopupVisible ? 1 : 0.9
|
||||
|
||||
@@ -97,11 +94,9 @@ PanelWindow {
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
// Remove layer rendering for better performance
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
|
||||
// Material 3 elevation with multiple layers
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -3
|
||||
@@ -273,7 +268,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// No battery info card
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 80
|
||||
@@ -317,7 +311,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Battery details
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
@@ -334,7 +327,6 @@ PanelWindow {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
// Health
|
||||
Column {
|
||||
spacing: 2
|
||||
width: (parent.width - Theme.spacingXL) / 2
|
||||
@@ -360,7 +352,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Capacity
|
||||
Column {
|
||||
spacing: 2
|
||||
width: (parent.width - Theme.spacingXL) / 2
|
||||
@@ -384,7 +375,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Power profiles
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
@@ -465,7 +455,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Degradation reason warning
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 60
|
||||
|
||||
@@ -10,7 +10,6 @@ Rectangle {
|
||||
|
||||
signal clicked()
|
||||
|
||||
// Helper function for consistent WiFi signal icons
|
||||
function getWiFiSignalIcon(signalStrength) {
|
||||
switch (signalStrength) {
|
||||
case "excellent":
|
||||
@@ -40,7 +39,6 @@ Rectangle {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
// Network Status Icon
|
||||
DankIcon {
|
||||
name: {
|
||||
if (NetworkService.networkStatus === "ethernet")
|
||||
@@ -56,7 +54,6 @@ Rectangle {
|
||||
visible: true
|
||||
}
|
||||
|
||||
// Bluetooth Icon (when available and enabled) - moved next to network
|
||||
DankIcon {
|
||||
name: "bluetooth"
|
||||
size: Theme.iconSize - 8
|
||||
@@ -65,7 +62,6 @@ Rectangle {
|
||||
visible: BluetoothService.available && BluetoothService.enabled
|
||||
}
|
||||
|
||||
// Audio Icon with scroll wheel support
|
||||
Rectangle {
|
||||
width: audioIcon.implicitWidth + 4
|
||||
height: audioIcon.implicitHeight + 4
|
||||
@@ -82,9 +78,6 @@ Rectangle {
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
// Scroll up - increase volume
|
||||
// Scroll down - decrease volume
|
||||
|
||||
id: audioWheelArea
|
||||
|
||||
anchors.fill: parent
|
||||
@@ -108,7 +101,6 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
// Microphone Icon (when active)
|
||||
DankIcon {
|
||||
name: "mic"
|
||||
size: Theme.iconSize - 8
|
||||
|
||||
@@ -16,7 +16,6 @@ Rectangle {
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
// Only show background when there's content to display
|
||||
if (!FocusedWindowService.focusedAppName && !FocusedWindowService.focusedWindowTitle)
|
||||
return "transparent";
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ Rectangle {
|
||||
color: Prefs.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
|
||||
}
|
||||
|
||||
// Notification dot indicator
|
||||
Rectangle {
|
||||
width: 8
|
||||
height: 8
|
||||
|
||||
@@ -13,7 +13,6 @@ Rectangle {
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
// Only show background when there are system tray items to display
|
||||
if (SystemTray.items.values.length === 0)
|
||||
return "transparent";
|
||||
|
||||
|
||||
@@ -39,11 +39,9 @@ PanelWindow {
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
// Material 3 animations
|
||||
opacity: showContextMenu ? 1 : 0
|
||||
scale: showContextMenu ? 1 : 0.85
|
||||
|
||||
// Material 3 drop shadow
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 4
|
||||
@@ -65,11 +63,9 @@ PanelWindow {
|
||||
menu: currentTrayItem && currentTrayItem.hasMenu ? currentTrayItem.menu : null
|
||||
}
|
||||
|
||||
// Custom menu styling using ListView
|
||||
ListView {
|
||||
id: menuList
|
||||
|
||||
// Calculate maximum text width for dynamic menu sizing
|
||||
property real maxTextWidth: {
|
||||
let maxWidth = 0;
|
||||
if (model && model.values) {
|
||||
@@ -101,7 +97,6 @@ PanelWindow {
|
||||
radius: modelData.isSeparator ? 0 : Theme.cornerRadiusSmall
|
||||
color: modelData.isSeparator ? "transparent" : (menuItemArea.containsMouse ? Theme.primaryHover : "transparent")
|
||||
|
||||
// Separator line
|
||||
Rectangle {
|
||||
visible: modelData.isSeparator
|
||||
anchors.centerIn: parent
|
||||
@@ -110,7 +105,6 @@ PanelWindow {
|
||||
color: Theme.surfaceVariantAlpha
|
||||
}
|
||||
|
||||
// Menu item content
|
||||
Row {
|
||||
visible: !modelData.isSeparator
|
||||
anchors.left: parent.left
|
||||
@@ -176,7 +170,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Click outside to close
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
|
||||
@@ -125,7 +125,6 @@ PanelWindow {
|
||||
id: topBarContent
|
||||
|
||||
readonly property int availableWidth: width
|
||||
// Use estimated fixed widths to break circular dependencies
|
||||
readonly property int launcherButtonWidth: 40
|
||||
readonly property int workspaceSwitcherWidth: 120 // Approximate
|
||||
readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference
|
||||
@@ -228,7 +227,6 @@ PanelWindow {
|
||||
anchors.bottomMargin: Theme.spacingXS
|
||||
clip: true
|
||||
|
||||
// Dynamic left section
|
||||
Row {
|
||||
id: leftSection
|
||||
|
||||
@@ -357,8 +355,8 @@ PanelWindow {
|
||||
item.onWidthChanged.connect(centerSection.updateLayout);
|
||||
if (model.widgetId === "spacer")
|
||||
item.spacerSize = Qt.binding(() => {
|
||||
return model.size || 20;
|
||||
});
|
||||
return model.size || 20;
|
||||
});
|
||||
|
||||
Qt.callLater(centerSection.updateLayout);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ Rectangle {
|
||||
|
||||
signal clicked()
|
||||
|
||||
// Visibility is now controlled by TopBar.qml
|
||||
width: visible ? Math.min(100, weatherRow.implicitWidth + Theme.spacingS * 2) : 0
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
@@ -83,10 +83,8 @@ Rectangle {
|
||||
target: NiriService
|
||||
}
|
||||
|
||||
// Force update when padding preference changes
|
||||
Connections {
|
||||
function onShowWorkspacePaddingChanged() {
|
||||
// Force re-evaluation by updating the property
|
||||
var baseList = root.getDisplayWorkspaces();
|
||||
root.workspaceList = Prefs.showWorkspacePadding ? root.padWorkspaces(baseList) : baseList;
|
||||
}
|
||||
@@ -128,7 +126,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Show index for placeholders if Prefs.showWorkspaceIndex is true, otherwise show a subtle dot
|
||||
StyledText {
|
||||
visible: Prefs.showWorkspaceIndex
|
||||
anchors.centerIn: parent
|
||||
|
||||
Reference in New Issue
Block a user