From 304d7afd13fee4779660f52962dfc590384b41de Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 04:49:49 +0100 Subject: [PATCH 1/8] Update ContentView.swift --- App/ContentView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index 65bd179..865ac12 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -219,7 +219,7 @@ struct ContentView: View { } label: { Text("Unload") .fontWeight(.semibold) - .foregroundStyle(.primary.opacity(0.68)) + .foregroundStyle(.primary.opacity(0.78)) .padding(.vertical, 9) .padding(.horizontal, 16) .background(Color.gray.opacity(0.18)) From 7a16920691549e995dd0628488c63dd4b307db6f Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 04:53:39 +0100 Subject: [PATCH 2/8] Update ContentView.swift From 17dc6e88d92231c3ae721d61f9eb71980379e9dc Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 05:03:12 +0100 Subject: [PATCH 3/8] Update ContentView.swift --- App/ContentView.swift | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index 865ac12..ff353ac 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -171,7 +171,7 @@ struct ContentView: View { ScrollView { VStack(spacing: 18) { - VStack(alignment: .leading, spacing: 5) { + VStack(alignment: .leading, spacing: 6) { HStack(alignment: .firstTextBaseline, spacing: 10) { Text("IPAID") .font(.largeTitle.bold()) @@ -181,24 +181,15 @@ struct ContentView: View { .foregroundStyle(.secondary) } - Text("Bundle IDs • Names • Extensions") - .font(.callout.weight(.semibold)) - .foregroundStyle(.secondary) - } - .frame(maxWidth: .infinity, alignment: .leading) - - if !originalFileName.isEmpty { - VStack(alignment: .leading, spacing: 4) { - Text("Loaded IPA") - .font(.caption.weight(.semibold)) + if !originalFileName.isEmpty { + Text("Loaded: \(displayedOriginalFileName)") + .font(.callout.weight(.medium)) .foregroundStyle(.secondary) - - Text(displayedOriginalFileName) - .font(.callout) .lineLimit(1) + .truncationMode(.middle) } - .frame(maxWidth: .infinity, alignment: .leading) } + .frame(maxWidth: .infinity, alignment: .leading) if currentBundleID.isEmpty && !status.isEmpty { Text(status) @@ -235,7 +226,7 @@ struct ContentView: View { .frame(maxWidth: .infinity, alignment: .leading) if !currentBundleID.isEmpty { - VStack(alignment: .leading, spacing: 10) { + VStack(alignment: .leading, spacing: 8) { Text("Current Bundle ID") .font(.headline.weight(.semibold)) @@ -327,11 +318,15 @@ struct ContentView: View { .font(.callout.weight(.semibold)) Spacer() } - .padding(.vertical, 12) + .padding(.vertical, 11) .padding(.horizontal, 14) - .foregroundStyle(duplicateMode ? Color.white : Color.primary) - .background(duplicateMode ? Color.blue : Color.gray.opacity(0.18)) - .clipShape(RoundedRectangle(cornerRadius: 14)) + .foregroundStyle(duplicateMode ? Color.blue : Color.primary) + .background(Color.gray.opacity(0.12)) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(duplicateMode ? Color.blue.opacity(0.7) : Color.white.opacity(0.06), lineWidth: 1) + ) + .clipShape(RoundedRectangle(cornerRadius: 12)) } .buttonStyle(.plain) From 83eaa107d8c6751bbe6e3f2c3e8bd60638d7aa7d Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 05:13:10 +0100 Subject: [PATCH 4/8] Update ContentView.swift --- App/ContentView.swift | 62 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index ff353ac..2f107d5 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -123,7 +123,7 @@ struct ContentView: View { case .orange: return .orange case .green: - return .green + return .blue case .none: return .secondary } @@ -198,7 +198,7 @@ struct ContentView: View { .frame(maxWidth: .infinity, alignment: .leading) } - HStack(spacing: 10) { + HStack(spacing: 8) { Button("Select IPA") { showPicker = true } @@ -226,7 +226,7 @@ struct ContentView: View { .frame(maxWidth: .infinity, alignment: .leading) if !currentBundleID.isEmpty { - VStack(alignment: .leading, spacing: 8) { + VStack(alignment: .leading, spacing: 6) { Text("Current Bundle ID") .font(.headline.weight(.semibold)) @@ -262,7 +262,7 @@ struct ContentView: View { .font(.headline.weight(.semibold)) .padding(.top, 8) - HStack(spacing: 10) { + HStack(spacing: 8) { TextField("com.example.app", text: $newBundleID) .textInputAutocapitalization(.never) .autocorrectionDisabled() @@ -324,7 +324,7 @@ struct ContentView: View { .background(Color.gray.opacity(0.12)) .overlay( RoundedRectangle(cornerRadius: 12) - .stroke(duplicateMode ? Color.blue.opacity(0.7) : Color.white.opacity(0.06), lineWidth: 1) + .stroke(Color.white.opacity(0.06), lineWidth: 1) ) .clipShape(RoundedRectangle(cornerRadius: 12)) } @@ -338,7 +338,7 @@ struct ContentView: View { .font(.headline.weight(.semibold)) .padding(.top, 8) - HStack(spacing: 10) { + HStack(spacing: 8) { TextField("App name", text: $displayName) .font(.body.weight(.regular)) .lineLimit(1) @@ -451,7 +451,7 @@ struct ContentView: View { } private var extensionRemovalSection: some View { - VStack(alignment: .leading, spacing: 10) { + VStack(alignment: .leading, spacing: 8) { Button { withAnimation(.easeInOut(duration: 0.2)) { extensionsExpanded.toggle() @@ -469,7 +469,7 @@ struct ContentView: View { Text("\(selectedExtensionsToRemove.count) of \(foundExtensions.count) selected") .font(.caption) - .foregroundStyle(selectedExtensionsToRemove.isEmpty ? Color.secondary : Color.white.opacity(0.85)) + .foregroundStyle(.secondary) } Spacer() @@ -477,11 +477,11 @@ struct ContentView: View { Image(systemName: extensionsExpanded ? "chevron.up" : "chevron.down") .font(.caption.bold()) } - .padding(.vertical, 12) + .padding(.vertical, 11) .padding(.horizontal, 14) - .foregroundStyle(selectedExtensionsToRemove.isEmpty ? Color.primary : Color.white) - .background(selectedExtensionsToRemove.isEmpty ? Color.gray.opacity(0.18) : Color.blue) - .clipShape(RoundedRectangle(cornerRadius: 14)) + .foregroundStyle(selectedExtensionsToRemove.isEmpty ? Color.primary : Color.blue) + .background(Color.gray.opacity(0.14)) + .clipShape(RoundedRectangle(cornerRadius: 12)) } .buttonStyle(.plain) @@ -505,22 +505,22 @@ struct ContentView: View { Image(systemName: selectedExtensionsToRemove.count == foundExtensions.count ? "checkmark.circle.fill" : "circle") .font(.title3) - Text(selectedExtensionsToRemove.count == foundExtensions.count ? "Deselect All Extensions" : "Select All Extensions") - .font(.callout.weight(.semibold)) + Text(selectedExtensionsToRemove.count == foundExtensions.count ? "Deselect All" : "Select All") + .font(.subheadline.weight(.semibold)) Spacer() } - .font(.callout) - .padding(.vertical, 10) - .padding(.horizontal, 12) - .background(Color.gray.opacity(0.12)) - .clipShape(RoundedRectangle(cornerRadius: 12)) + .font(.subheadline) + .padding(.vertical, 8) + .padding(.horizontal, 10) + .background(Color.gray.opacity(0.10)) + .clipShape(RoundedRectangle(cornerRadius: 10)) } .buttonStyle(.plain) } - .padding(12) - .background(Color.gray.opacity(0.08)) - .clipShape(RoundedRectangle(cornerRadius: 14)) + .padding(8) + .background(Color.gray.opacity(0.07)) + .clipShape(RoundedRectangle(cornerRadius: 12)) } } } @@ -530,7 +530,7 @@ struct ContentView: View { let isExpanded = expandedExtensionInfo == path let name = extensionName(from: path) - return VStack(alignment: .leading, spacing: 8) { + return VStack(alignment: .leading, spacing: 6) { HStack(spacing: 0) { Button { withAnimation(.easeInOut(duration: 0.18)) { @@ -542,7 +542,7 @@ struct ContentView: View { clearStaleExportState() } } label: { - HStack(spacing: 10) { + HStack(spacing: 8) { Image(systemName: isSelected ? "checkmark.circle.fill" : "circle") .font(.title3) .foregroundStyle(isSelected ? Color.blue : Color.secondary) @@ -586,7 +586,7 @@ struct ContentView: View { } label: { Image(systemName: "info.circle.fill") .foregroundStyle(Color.blue) - .frame(width: 44, height: 38) + .frame(width: 42, height: 34) .contentShape(Rectangle()) } .buttonStyle(.plain) @@ -601,12 +601,12 @@ struct ContentView: View { .transition(.opacity.combined(with: .move(edge: .top))) } } - .font(.callout) - .padding(.vertical, isExpanded ? 10 : 8) - .padding(.leading, 12) - .padding(.trailing, 6) - .background(Color.gray.opacity(0.12)) - .clipShape(RoundedRectangle(cornerRadius: 12)) + .font(.subheadline) + .padding(.vertical, isExpanded ? 8 : 6) + .padding(.leading, 10) + .padding(.trailing, 5) + .background(Color.gray.opacity(0.10)) + .clipShape(RoundedRectangle(cornerRadius: 10)) } From 373018e9f628c1b9f1821dc2f91a1aedad7bfe45 Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 14:16:13 +0100 Subject: [PATCH 5/8] Update ContentView.swift --- App/ContentView.swift | 54 +++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index 2f107d5..332d0dd 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -102,7 +102,7 @@ struct ContentView: View { } if !hasPendingChanges { - return .red + return .none } if !bundleIDChanged { @@ -369,9 +369,9 @@ struct ContentView: View { if !currentChangeMessage.isEmpty { Text(currentChangeMessage) - .font(.callout.weight(.regular)) + .font(.subheadline.weight(.regular)) .foregroundStyle(validationColor) - .padding(.top, 4) + .padding(.top, 3) } Button("Export Updated IPA") { @@ -477,7 +477,7 @@ struct ContentView: View { Image(systemName: extensionsExpanded ? "chevron.up" : "chevron.down") .font(.caption.bold()) } - .padding(.vertical, 11) + .padding(.vertical, 10) .padding(.horizontal, 14) .foregroundStyle(selectedExtensionsToRemove.isEmpty ? Color.primary : Color.blue) .background(Color.gray.opacity(0.14)) @@ -486,7 +486,7 @@ struct ContentView: View { .buttonStyle(.plain) if extensionsExpanded { - VStack(alignment: .leading, spacing: 8) { + VStack(alignment: .leading, spacing: 6) { ForEach(foundExtensions, id: \.self) { path in extensionRow(path) } @@ -503,24 +503,36 @@ struct ContentView: View { } label: { HStack { Image(systemName: selectedExtensionsToRemove.count == foundExtensions.count ? "checkmark.circle.fill" : "circle") - .font(.title3) + .font(.body) Text(selectedExtensionsToRemove.count == foundExtensions.count ? "Deselect All" : "Select All") .font(.subheadline.weight(.semibold)) Spacer() } - .font(.subheadline) - .padding(.vertical, 8) + .padding(.vertical, 7) .padding(.horizontal, 10) .background(Color.gray.opacity(0.10)) - .clipShape(RoundedRectangle(cornerRadius: 10)) + .clipShape(RoundedRectangle(cornerRadius: 9)) } .buttonStyle(.plain) + + if let infoPath = expandedExtensionInfo { + Text(extensionTip(for: extensionName(from: infoPath))) + .font(.caption.weight(.regular)) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + .padding(.vertical, 8) + .padding(.horizontal, 10) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Color.gray.opacity(0.10)) + .clipShape(RoundedRectangle(cornerRadius: 9)) + .transition(.opacity.combined(with: .move(edge: .top))) + } } - .padding(8) - .background(Color.gray.opacity(0.07)) - .clipShape(RoundedRectangle(cornerRadius: 12)) + .padding(7) + .background(Color.gray.opacity(0.06)) + .clipShape(RoundedRectangle(cornerRadius: 11)) } } } @@ -544,7 +556,7 @@ struct ContentView: View { } label: { HStack(spacing: 8) { Image(systemName: isSelected ? "checkmark.circle.fill" : "circle") - .font(.title3) + .font(.body) .foregroundStyle(isSelected ? Color.blue : Color.secondary) Text(name) @@ -586,27 +598,19 @@ struct ContentView: View { } label: { Image(systemName: "info.circle.fill") .foregroundStyle(Color.blue) - .frame(width: 42, height: 34) + .frame(width: 40, height: 30) .contentShape(Rectangle()) } .buttonStyle(.plain) } - if isExpanded { - Text(extensionTip(for: name)) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - .padding(.leading, 32) - .transition(.opacity.combined(with: .move(edge: .top))) - } } .font(.subheadline) - .padding(.vertical, isExpanded ? 8 : 6) + .padding(.vertical, 5) .padding(.leading, 10) .padding(.trailing, 5) - .background(Color.gray.opacity(0.10)) - .clipShape(RoundedRectangle(cornerRadius: 10)) + .background(isExpanded ? Color.gray.opacity(0.14) : Color.gray.opacity(0.10)) + .clipShape(RoundedRectangle(cornerRadius: 9)) } From 19f53ba84f20322789ebb77f5e8598429031b472 Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 14:22:17 +0100 Subject: [PATCH 6/8] Update ContentView.swift --- App/ContentView.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index 332d0dd..25f942d 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -336,7 +336,7 @@ struct ContentView: View { Text("Display Name") .font(.headline.weight(.semibold)) - .padding(.top, 8) + .padding(.top, 2) HStack(spacing: 8) { TextField("App name", text: $displayName) @@ -469,7 +469,7 @@ struct ContentView: View { Text("\(selectedExtensionsToRemove.count) of \(foundExtensions.count) selected") .font(.caption) - .foregroundStyle(.secondary) + .foregroundStyle(.secondary.opacity(0.78)) } Spacer() @@ -519,14 +519,14 @@ struct ContentView: View { if let infoPath = expandedExtensionInfo { Text(extensionTip(for: extensionName(from: infoPath))) - .font(.caption.weight(.regular)) - .foregroundStyle(.secondary) + .font(.caption2.weight(.regular)) + .foregroundStyle(.secondary.opacity(0.86)) .fixedSize(horizontal: false, vertical: true) - .padding(.vertical, 8) - .padding(.horizontal, 10) + .padding(.vertical, 6) + .padding(.horizontal, 9) .frame(maxWidth: .infinity, alignment: .leading) - .background(Color.gray.opacity(0.10)) - .clipShape(RoundedRectangle(cornerRadius: 9)) + .background(Color.gray.opacity(0.075)) + .clipShape(RoundedRectangle(cornerRadius: 8)) .transition(.opacity.combined(with: .move(edge: .top))) } } From b2bb7fd60786607826983dc69c5321e06e57cb58 Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 14:35:00 +0100 Subject: [PATCH 7/8] Update ContentView.swift --- App/ContentView.swift | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index 25f942d..67d0f9d 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -21,6 +21,7 @@ struct ContentView: View { @State private var extensionsExpanded = false @State private var expandedExtensionInfo: String? @State private var infoTapLocked = false + @State private var infoAutoCloseToken = UUID() @State private var copiedFilename = false @State private var copiedBundleID = false @State private var exportSummary = "" @@ -456,28 +457,28 @@ struct ContentView: View { withAnimation(.easeInOut(duration: 0.2)) { extensionsExpanded.toggle() if !extensionsExpanded { + infoAutoCloseToken = UUID() expandedExtensionInfo = nil } } } label: { - HStack { + HStack(spacing: 8) { Image(systemName: selectedExtensionsToRemove.isEmpty ? "circle" : "checkmark.circle.fill") - VStack(alignment: .leading, spacing: 2) { - Text("Remove Extensions") - .font(.callout.weight(.semibold)) + Text("Remove Extensions") + .font(.callout.weight(.semibold)) - Text("\(selectedExtensionsToRemove.count) of \(foundExtensions.count) selected") - .font(.caption) - .foregroundStyle(.secondary.opacity(0.78)) - } + Text("• \(selectedExtensionsToRemove.count)/\(foundExtensions.count) Selected") + .font(.callout.weight(.medium)) + .foregroundStyle(.secondary.opacity(0.78)) + .lineLimit(1) Spacer() Image(systemName: extensionsExpanded ? "chevron.up" : "chevron.down") .font(.caption.bold()) } - .padding(.vertical, 10) + .padding(.vertical, 9) .padding(.horizontal, 14) .foregroundStyle(selectedExtensionsToRemove.isEmpty ? Color.primary : Color.blue) .background(Color.gray.opacity(0.14)) @@ -582,13 +583,21 @@ struct ContentView: View { infoTapLocked = false } - withAnimation(.easeInOut(duration: 0.18)) { - expandedExtensionInfo = isExpanded ? nil : path - } + if isExpanded { + infoAutoCloseToken = UUID() + withAnimation(.easeInOut(duration: 0.18)) { + expandedExtensionInfo = nil + } + } else { + let token = UUID() + infoAutoCloseToken = token + + withAnimation(.easeInOut(duration: 0.18)) { + expandedExtensionInfo = path + } - if !isExpanded { DispatchQueue.main.asyncAfter(deadline: .now() + 10) { - if expandedExtensionInfo == path { + if infoAutoCloseToken == token && expandedExtensionInfo == path { withAnimation(.easeInOut(duration: 0.18)) { expandedExtensionInfo = nil } From e252fff43081b5ab3b353ffde52fd6cf6e9be601 Mon Sep 17 00:00:00 2001 From: shplash Date: Mon, 11 May 2026 14:42:36 +0100 Subject: [PATCH 8/8] Update ContentView.swift --- App/ContentView.swift | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/App/ContentView.swift b/App/ContentView.swift index 67d0f9d..b0814b2 100644 --- a/App/ContentView.swift +++ b/App/ContentView.swift @@ -462,26 +462,27 @@ struct ContentView: View { } } } label: { - HStack(spacing: 8) { + HStack { Image(systemName: selectedExtensionsToRemove.isEmpty ? "circle" : "checkmark.circle.fill") - Text("Remove Extensions") + Text("Extensions • \(selectedExtensionsToRemove.count)/\(foundExtensions.count)") .font(.callout.weight(.semibold)) - - Text("• \(selectedExtensionsToRemove.count)/\(foundExtensions.count) Selected") - .font(.callout.weight(.medium)) - .foregroundStyle(.secondary.opacity(0.78)) .lineLimit(1) + .minimumScaleFactor(0.85) Spacer() Image(systemName: extensionsExpanded ? "chevron.up" : "chevron.down") .font(.caption.bold()) } - .padding(.vertical, 9) + .padding(.vertical, 11) .padding(.horizontal, 14) .foregroundStyle(selectedExtensionsToRemove.isEmpty ? Color.primary : Color.blue) - .background(Color.gray.opacity(0.14)) + .background(Color.gray.opacity(0.12)) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(Color.white.opacity(0.06), lineWidth: 1) + ) .clipShape(RoundedRectangle(cornerRadius: 12)) } .buttonStyle(.plain)