AppIconView.swift 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import SwiftUI
  2. import AppKit
  3. struct AppIconView: View {
  4. let app: LauncherApp
  5. let size: CGFloat
  6. var showAppBackground: Bool = true
  7. var iconPaddingFactor: CGFloat = 0.12
  8. @Environment(\.colorScheme) private var colorScheme
  9. var body: some View {
  10. ZStack {
  11. if app.isCreateNew {
  12. RoundedRectangle(cornerRadius: 18, style: .continuous)
  13. .stroke(createTileStrokeColor, lineWidth: 2)
  14. .background(
  15. RoundedRectangle(cornerRadius: 18, style: .continuous)
  16. .fill(createTileFillColor)
  17. )
  18. Image(systemName: "plus")
  19. .font(.system(size: size * 0.34, weight: .regular))
  20. .foregroundStyle(createTileIconColor)
  21. } else {
  22. if showAppBackground {
  23. RoundedRectangle(cornerRadius: 18, style: .continuous)
  24. .fill(LinearGradient(colors: gradientColors, startPoint: .topLeading, endPoint: .bottomTrailing))
  25. RoundedRectangle(cornerRadius: 18, style: .continuous)
  26. .stroke(Color.white.opacity(0.08), lineWidth: 1)
  27. }
  28. if let webURL = app.webURL {
  29. WebSiteFaviconView(
  30. webURL: webURL,
  31. size: size,
  32. assetIconName: app.assetIconName,
  33. fallbackSymbolName: app.fallbackSymbolName,
  34. iconPaddingFactor: iconPaddingFactor
  35. )
  36. } else if let iconImage = NSImage(named: app.assetIconName) {
  37. Image(nsImage: iconImage)
  38. .resizable()
  39. .scaledToFit()
  40. .padding(size * iconPaddingFactor)
  41. } else {
  42. Image(systemName: app.fallbackSymbolName)
  43. .font(.system(size: size * 0.32, weight: .semibold))
  44. .foregroundStyle(.white)
  45. .padding(size * iconPaddingFactor)
  46. }
  47. }
  48. }
  49. .frame(width: size, height: size)
  50. }
  51. private var gradientColors: [Color] {
  52. switch app.name {
  53. case let name where name.contains("Gmail"):
  54. return [Color.red.opacity(0.85), Color.orange.opacity(0.8)]
  55. case let name where name.contains("Docs"):
  56. return [Color.blue.opacity(0.9), Color.indigo.opacity(0.85)]
  57. case let name where name.contains("Drive"):
  58. return [Color.green.opacity(0.9), Color.blue.opacity(0.75)]
  59. case let name where name.contains("YouTube"):
  60. return [Color.red.opacity(0.95), Color.pink.opacity(0.75)]
  61. case let name where name.contains("Maps"):
  62. return [Color.green.opacity(0.85), Color.teal.opacity(0.75)]
  63. default:
  64. return [Color.blue.opacity(0.85), Color.cyan.opacity(0.7)]
  65. }
  66. }
  67. private var createTileStrokeColor: Color {
  68. colorScheme == .dark ? Color.white.opacity(0.35) : Color.black.opacity(0.22)
  69. }
  70. private var createTileFillColor: Color {
  71. colorScheme == .dark ? Color.white.opacity(0.03) : Color.white.opacity(0.85)
  72. }
  73. private var createTileIconColor: Color {
  74. colorScheme == .dark ? Color.white.opacity(0.9) : Color.primary.opacity(0.88)
  75. }
  76. }