|
@@ -12,6 +12,7 @@ struct WidgetsRootView: View {
|
|
|
|
|
|
|
|
@ObservedObject private var desktopWidgetManager = DesktopWidgetWindowManager.shared
|
|
@ObservedObject private var desktopWidgetManager = DesktopWidgetWindowManager.shared
|
|
|
@ObservedObject private var premiumStore = PremiumStore.shared
|
|
@ObservedObject private var premiumStore = PremiumStore.shared
|
|
|
|
|
+ @Environment(\.colorScheme) private var colorScheme
|
|
|
@State private var query = ""
|
|
@State private var query = ""
|
|
|
@State private var toastMessage: String?
|
|
@State private var toastMessage: String?
|
|
|
enum ToastKind {
|
|
enum ToastKind {
|
|
@@ -44,7 +45,7 @@ struct WidgetsRootView: View {
|
|
|
.frame(width: 260)
|
|
.frame(width: 260)
|
|
|
|
|
|
|
|
Divider()
|
|
Divider()
|
|
|
- .overlay(Color.white.opacity(0.08))
|
|
|
|
|
|
|
+ .overlay(dividerColor)
|
|
|
|
|
|
|
|
mainContent
|
|
mainContent
|
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
|
@@ -70,25 +71,25 @@ struct WidgetsRootView: View {
|
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
|
Text("All Widgets")
|
|
Text("All Widgets")
|
|
|
.font(.system(size: 16, weight: .bold))
|
|
.font(.system(size: 16, weight: .bold))
|
|
|
- .foregroundStyle(.white.opacity(0.92))
|
|
|
|
|
|
|
+ .foregroundStyle(primaryTextColor)
|
|
|
.padding(.top, 6)
|
|
.padding(.top, 6)
|
|
|
|
|
|
|
|
HStack(spacing: 10) {
|
|
HStack(spacing: 10) {
|
|
|
Image(systemName: "magnifyingglass")
|
|
Image(systemName: "magnifyingglass")
|
|
|
- .foregroundStyle(.white.opacity(0.7))
|
|
|
|
|
|
|
+ .foregroundStyle(secondaryTextColor)
|
|
|
TextField("Search widgets", text: $query)
|
|
TextField("Search widgets", text: $query)
|
|
|
.textFieldStyle(.plain)
|
|
.textFieldStyle(.plain)
|
|
|
- .foregroundStyle(.white.opacity(0.94))
|
|
|
|
|
|
|
+ .foregroundStyle(primaryTextColor)
|
|
|
}
|
|
}
|
|
|
.padding(.horizontal, 12)
|
|
.padding(.horizontal, 12)
|
|
|
.padding(.vertical, 9)
|
|
.padding(.vertical, 9)
|
|
|
.background(
|
|
.background(
|
|
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
|
|
- .fill(Color.black.opacity(0.22))
|
|
|
|
|
|
|
+ .fill(searchBackgroundColor)
|
|
|
)
|
|
)
|
|
|
.overlay(
|
|
.overlay(
|
|
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
|
|
- .stroke(Color.white.opacity(0.08), lineWidth: 1)
|
|
|
|
|
|
|
+ .stroke(searchStrokeColor, lineWidth: 1)
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
ScrollView {
|
|
ScrollView {
|
|
@@ -111,11 +112,11 @@ struct WidgetsRootView: View {
|
|
|
.padding(.vertical, 10)
|
|
.padding(.vertical, 10)
|
|
|
.background(
|
|
.background(
|
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
|
- .fill(Color.white.opacity(0.03))
|
|
|
|
|
|
|
+ .fill(panelFillColor)
|
|
|
)
|
|
)
|
|
|
.overlay(
|
|
.overlay(
|
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
|
- .stroke(Color.white.opacity(0.06), lineWidth: 1)
|
|
|
|
|
|
|
+ .stroke(panelStrokeColor, lineWidth: 1)
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -126,7 +127,7 @@ struct WidgetsRootView: View {
|
|
|
|
|
|
|
|
Text("Widget")
|
|
Text("Widget")
|
|
|
.font(.system(size: 13, weight: .semibold))
|
|
.font(.system(size: 13, weight: .semibold))
|
|
|
- .foregroundStyle(.white.opacity(0.75))
|
|
|
|
|
|
|
+ .foregroundStyle(secondaryTextColor)
|
|
|
.padding(.top, 4)
|
|
.padding(.top, 4)
|
|
|
|
|
|
|
|
HStack(alignment: .top, spacing: 18) {
|
|
HStack(alignment: .top, spacing: 18) {
|
|
@@ -151,11 +152,11 @@ struct WidgetsRootView: View {
|
|
|
.padding(.vertical, 10)
|
|
.padding(.vertical, 10)
|
|
|
.background(
|
|
.background(
|
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
|
- .fill(Color.white.opacity(0.02))
|
|
|
|
|
|
|
+ .fill(panelSecondaryFillColor)
|
|
|
)
|
|
)
|
|
|
.overlay(
|
|
.overlay(
|
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
|
|
- .stroke(Color.white.opacity(0.06), lineWidth: 1)
|
|
|
|
|
|
|
+ .stroke(panelStrokeColor, lineWidth: 1)
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -166,10 +167,10 @@ struct WidgetsRootView: View {
|
|
|
VStack(alignment: .leading, spacing: 3) {
|
|
VStack(alignment: .leading, spacing: 3) {
|
|
|
Text(app.name)
|
|
Text(app.name)
|
|
|
.font(.system(size: 20, weight: .bold))
|
|
.font(.system(size: 20, weight: .bold))
|
|
|
- .foregroundStyle(.white.opacity(0.94))
|
|
|
|
|
|
|
+ .foregroundStyle(primaryTextColor)
|
|
|
Text("Click a widget card to add it. Click again to remove it.")
|
|
Text("Click a widget card to add it. Click again to remove it.")
|
|
|
.font(.system(size: 12.5, weight: .medium))
|
|
.font(.system(size: 12.5, weight: .medium))
|
|
|
- .foregroundStyle(.white.opacity(0.65))
|
|
|
|
|
|
|
+ .foregroundStyle(tertiaryTextColor)
|
|
|
}
|
|
}
|
|
|
Spacer()
|
|
Spacer()
|
|
|
}
|
|
}
|
|
@@ -179,13 +180,13 @@ struct WidgetsRootView: View {
|
|
|
VStack(spacing: 10) {
|
|
VStack(spacing: 10) {
|
|
|
Image(systemName: "widget.small")
|
|
Image(systemName: "widget.small")
|
|
|
.font(.system(size: 30, weight: .semibold))
|
|
.font(.system(size: 30, weight: .semibold))
|
|
|
- .foregroundStyle(.white.opacity(0.75))
|
|
|
|
|
|
|
+ .foregroundStyle(secondaryTextColor)
|
|
|
Text("Select an app to preview widgets")
|
|
Text("Select an app to preview widgets")
|
|
|
.font(.title3.weight(.semibold))
|
|
.font(.title3.weight(.semibold))
|
|
|
- .foregroundStyle(.white.opacity(0.9))
|
|
|
|
|
|
|
+ .foregroundStyle(primaryTextColor)
|
|
|
Text("Pick any app from the left to customize its widget.")
|
|
Text("Pick any app from the left to customize its widget.")
|
|
|
.font(.subheadline)
|
|
.font(.subheadline)
|
|
|
- .foregroundStyle(.white.opacity(0.7))
|
|
|
|
|
|
|
+ .foregroundStyle(secondaryTextColor)
|
|
|
}
|
|
}
|
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
|
}
|
|
}
|
|
@@ -258,6 +259,42 @@ struct WidgetsRootView: View {
|
|
|
toastKind = nil
|
|
toastKind = nil
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ private var primaryTextColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.94) : .primary.opacity(0.95)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var secondaryTextColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.75) : .primary.opacity(0.72)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var tertiaryTextColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.65) : .primary.opacity(0.60)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var dividerColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.08) : .black.opacity(0.08)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var searchBackgroundColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .black.opacity(0.22) : .white.opacity(0.78)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var searchStrokeColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.08) : .black.opacity(0.08)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var panelFillColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.03) : .white.opacity(0.82)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var panelSecondaryFillColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.02) : .white.opacity(0.72)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private var panelStrokeColor: Color {
|
|
|
|
|
+ colorScheme == .dark ? .white.opacity(0.06) : .black.opacity(0.07)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private struct WidgetSidebarRow: View {
|
|
private struct WidgetSidebarRow: View {
|
|
@@ -266,6 +303,7 @@ private struct WidgetSidebarRow: View {
|
|
|
let onSelect: () -> Void
|
|
let onSelect: () -> Void
|
|
|
|
|
|
|
|
@State private var hovering = false
|
|
@State private var hovering = false
|
|
|
|
|
+ @Environment(\.colorScheme) private var colorScheme
|
|
|
|
|
|
|
|
var body: some View {
|
|
var body: some View {
|
|
|
Button(action: onSelect) {
|
|
Button(action: onSelect) {
|
|
@@ -273,7 +311,7 @@ private struct WidgetSidebarRow: View {
|
|
|
AppIconView(app: app, size: 30, showAppBackground: false, iconPaddingFactor: 0.08)
|
|
AppIconView(app: app, size: 30, showAppBackground: false, iconPaddingFactor: 0.08)
|
|
|
Text(app.name)
|
|
Text(app.name)
|
|
|
.font(.system(size: 13.5, weight: .semibold))
|
|
.font(.system(size: 13.5, weight: .semibold))
|
|
|
- .foregroundStyle(.white.opacity(0.92))
|
|
|
|
|
|
|
+ .foregroundStyle(colorScheme == .dark ? .white.opacity(0.92) : .primary.opacity(0.92))
|
|
|
.lineLimit(1)
|
|
.lineLimit(1)
|
|
|
Spacer(minLength: 0)
|
|
Spacer(minLength: 0)
|
|
|
}
|
|
}
|
|
@@ -285,7 +323,12 @@ private struct WidgetSidebarRow: View {
|
|
|
)
|
|
)
|
|
|
.overlay(
|
|
.overlay(
|
|
|
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
|
|
- .stroke(Color.white.opacity(isSelected ? 0.18 : 0.06), lineWidth: 1)
|
|
|
|
|
|
|
+ .stroke(
|
|
|
|
|
+ colorScheme == .dark
|
|
|
|
|
+ ? Color.white.opacity(isSelected ? 0.18 : 0.06)
|
|
|
|
|
+ : Color.black.opacity(isSelected ? 0.16 : 0.06),
|
|
|
|
|
+ lineWidth: 1
|
|
|
|
|
+ )
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
.buttonStyle(.plain)
|
|
.buttonStyle(.plain)
|
|
@@ -293,9 +336,9 @@ private struct WidgetSidebarRow: View {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var backgroundFill: Color {
|
|
private var backgroundFill: Color {
|
|
|
- if isSelected { return Color.blue.opacity(0.18) }
|
|
|
|
|
- if hovering { return Color.white.opacity(0.06) }
|
|
|
|
|
- return Color.white.opacity(0.02)
|
|
|
|
|
|
|
+ if isSelected { return Color.blue.opacity(colorScheme == .dark ? 0.18 : 0.12) }
|
|
|
|
|
+ if hovering { return colorScheme == .dark ? Color.white.opacity(0.06) : Color.black.opacity(0.04) }
|
|
|
|
|
+ return colorScheme == .dark ? Color.white.opacity(0.02) : Color.black.opacity(0.015)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -352,6 +395,7 @@ private struct WidgetPreviewAddCard: View {
|
|
|
private struct DesktopWidgetToast: View {
|
|
private struct DesktopWidgetToast: View {
|
|
|
let message: String
|
|
let message: String
|
|
|
let kind: WidgetsRootView.ToastKind
|
|
let kind: WidgetsRootView.ToastKind
|
|
|
|
|
+ @Environment(\.colorScheme) private var colorScheme
|
|
|
|
|
|
|
|
private var iconAndTint: (String, Color) {
|
|
private var iconAndTint: (String, Color) {
|
|
|
switch kind {
|
|
switch kind {
|
|
@@ -371,7 +415,7 @@ private struct DesktopWidgetToast: View {
|
|
|
|
|
|
|
|
Text(message)
|
|
Text(message)
|
|
|
.font(.system(size: 14, weight: .semibold))
|
|
.font(.system(size: 14, weight: .semibold))
|
|
|
- .foregroundStyle(.white.opacity(0.95))
|
|
|
|
|
|
|
+ .foregroundStyle(colorScheme == .dark ? .white.opacity(0.95) : .primary.opacity(0.95))
|
|
|
.lineLimit(1)
|
|
.lineLimit(1)
|
|
|
.multilineTextAlignment(.leading)
|
|
.multilineTextAlignment(.leading)
|
|
|
|
|
|
|
@@ -382,11 +426,11 @@ private struct DesktopWidgetToast: View {
|
|
|
.frame(maxWidth: 560)
|
|
.frame(maxWidth: 560)
|
|
|
.background(
|
|
.background(
|
|
|
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
|
|
- .fill(Color.black.opacity(0.82))
|
|
|
|
|
|
|
+ .fill(colorScheme == .dark ? Color.black.opacity(0.82) : Color.white.opacity(0.95))
|
|
|
)
|
|
)
|
|
|
.overlay(
|
|
.overlay(
|
|
|
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
|
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
|
|
- .stroke(Color.white.opacity(0.08), lineWidth: 1)
|
|
|
|
|
|
|
+ .stroke(colorScheme == .dark ? Color.white.opacity(0.08) : Color.black.opacity(0.08), lineWidth: 1)
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|