mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 10:48:52 +00:00
Road to v4.0.0
This commit is contained in:
@@ -31,7 +31,7 @@ struct AppCommands: Commands {
|
||||
CommandGroup(replacing: .appInfo) {
|
||||
|
||||
Button {
|
||||
updater.checkForUpdates()
|
||||
updater.checkForUpdatesForce(showSheet: true)
|
||||
} label: {
|
||||
Text("Check for Updates")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// IceGroupBox.swift
|
||||
// Pearcleaner
|
||||
//
|
||||
// Created by Jordan Baird (Ice), modified for Pearcleaner usage by Alin Lupascu on 9/27/24.
|
||||
//
|
||||
import SwiftUI
|
||||
|
||||
struct PearGroupBox<Header: View, Content: View, Footer: View>: View {
|
||||
private let header: Header
|
||||
private let content: Content
|
||||
private let footer: Footer
|
||||
private let padding: CGFloat
|
||||
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// PearGroupBox(
|
||||
/// header: { Text("Header View") },
|
||||
/// content: { Text("Content View") },
|
||||
/// footer: { Text("Footer View") }
|
||||
/// )
|
||||
/// ```
|
||||
init(
|
||||
padding: CGFloat = 10,
|
||||
@ViewBuilder header: () -> Header,
|
||||
@ViewBuilder content: () -> Content,
|
||||
@ViewBuilder footer: () -> Footer
|
||||
) {
|
||||
self.padding = padding
|
||||
self.header = header()
|
||||
self.content = content()
|
||||
self.footer = footer()
|
||||
}
|
||||
|
||||
/// Example usage with no header:
|
||||
/// ```
|
||||
/// PearGroupBox(
|
||||
/// content: { Text("Content View") },
|
||||
/// footer: { Text("Footer View") }
|
||||
/// )
|
||||
/// ```
|
||||
init(
|
||||
padding: CGFloat = 10,
|
||||
@ViewBuilder content: () -> Content,
|
||||
@ViewBuilder footer: () -> Footer
|
||||
) where Header == EmptyView {
|
||||
self.init(padding: padding) {
|
||||
EmptyView()
|
||||
} content: {
|
||||
content()
|
||||
} footer: {
|
||||
footer()
|
||||
}
|
||||
}
|
||||
|
||||
/// Example usage with no footer:
|
||||
/// ```
|
||||
/// PearGroupBox(
|
||||
/// header: { Text("Header View") },
|
||||
/// content: { Text("Content View") }
|
||||
/// )
|
||||
/// ```
|
||||
init(
|
||||
padding: CGFloat = 10,
|
||||
@ViewBuilder header: () -> Header,
|
||||
@ViewBuilder content: () -> Content
|
||||
) where Footer == EmptyView {
|
||||
self.init(padding: padding) {
|
||||
header()
|
||||
} content: {
|
||||
content()
|
||||
} footer: {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
/// Example usage with content only:
|
||||
/// ```
|
||||
/// PearGroupBox {
|
||||
/// Text("Content View Only")
|
||||
/// }
|
||||
/// ```
|
||||
init(
|
||||
padding: CGFloat = 10,
|
||||
@ViewBuilder content: () -> Content
|
||||
) where Header == EmptyView, Footer == EmptyView {
|
||||
self.init(padding: padding) {
|
||||
EmptyView()
|
||||
} content: {
|
||||
content()
|
||||
} footer: {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
/// Example usage with a title and content only:
|
||||
/// ```
|
||||
/// PearGroupBox("Header Title") {
|
||||
/// Text("Content View")
|
||||
/// }
|
||||
/// ```
|
||||
init(
|
||||
_ title: LocalizedStringKey,
|
||||
padding: CGFloat = 10,
|
||||
@ViewBuilder content: () -> Content
|
||||
) where Header == Text, Footer == EmptyView {
|
||||
self.init(padding: padding) {
|
||||
Text(title)
|
||||
.font(.headline)
|
||||
} content: {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
header
|
||||
content
|
||||
.padding(padding)
|
||||
.background {
|
||||
backgroundShape
|
||||
.fill(.quinary)
|
||||
.overlay {
|
||||
backgroundShape
|
||||
.stroke(.quaternary)
|
||||
}
|
||||
}
|
||||
footer
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var backgroundShape: some Shape {
|
||||
RoundedRectangle(cornerRadius: 7, style: .circular)
|
||||
}
|
||||
}
|
||||
@@ -282,12 +282,37 @@ struct SimpleButtonBrightStyle: ButtonStyle {
|
||||
|
||||
|
||||
struct PearDropView: View {
|
||||
var multiplier: CGFloat = 1.0 // Multiplier parameter with a default value
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center, spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
LinearGradient(gradient: Gradient(colors: [.green, .orange]), startPoint: .leading, endPoint: .trailing)
|
||||
.frame(width: 220)
|
||||
.frame(width: 220 * multiplier) // Adjust the width based on the multiplier
|
||||
LinearGradient(gradient: Gradient(colors: [.orange, .primary.opacity(0.5)]), startPoint: .leading, endPoint: .trailing)
|
||||
.frame(width: 10 * multiplier) // Adjust the width based on the multiplier
|
||||
LinearGradient(gradient: Gradient(colors: [.primary.opacity(0.5), .primary.opacity(0.5)]), startPoint: .leading, endPoint: .trailing)
|
||||
.frame(width: 300 * multiplier) // Adjust the width based on the multiplier
|
||||
}
|
||||
.mask(
|
||||
Image("logo_text_small")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 500 * multiplier) // Scale the mask image width
|
||||
.padding()
|
||||
)
|
||||
}
|
||||
.frame(height: 120 * multiplier) // Adjust the height of the VStack based on the multiplier
|
||||
}
|
||||
}
|
||||
|
||||
struct PearDropViewSmall: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center, spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
LinearGradient(gradient: Gradient(colors: [.green, .orange]), startPoint: .leading, endPoint: .trailing)
|
||||
.frame(width: 260)
|
||||
LinearGradient(gradient: Gradient(colors: [.orange, .primary.opacity(0.5)]), startPoint: .leading, endPoint: .trailing)
|
||||
.frame(width: 10)
|
||||
LinearGradient(gradient: Gradient(colors: [.primary.opacity(0.5), .primary.opacity(0.5)]), startPoint: .leading, endPoint: .trailing)
|
||||
@@ -297,13 +322,10 @@ struct PearDropView: View {
|
||||
Image("logo_text_small")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 500)
|
||||
.padding()
|
||||
.frame(width: 180)
|
||||
)
|
||||
|
||||
}
|
||||
.frame(height: 120)
|
||||
|
||||
.frame(height: 50)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -703,6 +703,45 @@ extension URL {
|
||||
}
|
||||
}
|
||||
|
||||
// Removes the sidebar toggle button from the toolbar, if running on macOS 14.0 or newer.
|
||||
extension View {
|
||||
@ViewBuilder
|
||||
func removeSidebarToggle() -> some View {
|
||||
if #available(macOS 14.0, *) {
|
||||
self.toolbar(removing: .sidebarToggle)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drag window by background
|
||||
extension View {
|
||||
// Helper function to apply the movable background window
|
||||
func movableByWindowBackground() -> some View {
|
||||
self.background(MovableWindowAccessor())
|
||||
}
|
||||
}
|
||||
|
||||
// Custom NSWindow accessor to modify window properties
|
||||
struct MovableWindowAccessor: NSViewRepresentable {
|
||||
func makeNSView(context: Context) -> NSView {
|
||||
let nsView = NSView()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if let window = nsView.window {
|
||||
// Enable dragging by the window's background
|
||||
window.isMovableByWindowBackground = true
|
||||
}
|
||||
}
|
||||
|
||||
return nsView
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: NSView, context: Context) {}
|
||||
}
|
||||
|
||||
|
||||
// Return image for different folders
|
||||
func folderImages(for path: String) -> AnyView? {
|
||||
if path.contains("/Library/Containers/") || path.contains("/Library/Group Containers/") {
|
||||
|
||||
Reference in New Issue
Block a user