| | |
| | | .onExitCommand(perform: onCancel) |
| | | } |
| | | } |
| | | |
| | | struct UsageTipsCloseReminderBubble: View { |
| | | let title: String |
| | | let message: String |
| | | let previewCallout: String |
| | | let doNotRemindTitle: String |
| | | @Binding var doNotRemind: Bool |
| | | let confirmTitle: String |
| | | let onCancel: () -> Void |
| | | let onConfirm: () -> Void |
| | | |
| | | var body: some View { |
| | | VStack(alignment: .leading, spacing: 16) { |
| | | HStack(alignment: .top, spacing: 12) { |
| | | Text(title) |
| | | .font(.system(size: 22, weight: .bold)) |
| | | .foregroundStyle(.white) |
| | | .fixedSize(horizontal: false, vertical: true) |
| | | .frame(maxWidth: .infinity, alignment: .leading) |
| | | |
| | | Button(action: onCancel) { |
| | | Image(systemName: "xmark") |
| | | .font(.system(size: 12, weight: .bold)) |
| | | .foregroundStyle(.white.opacity(0.82)) |
| | | .frame(width: 26, height: 26) |
| | | .background(Circle().fill(Color.white.opacity(0.12))) |
| | | } |
| | | .buttonStyle(.plain) |
| | | .help(tr("tag.cancel")) |
| | | } |
| | | |
| | | UsageTipsCloseReminderSettingsPreview(callout: previewCallout) |
| | | |
| | | Text(message) |
| | | .font(.system(size: 15, weight: .medium)) |
| | | .lineSpacing(4) |
| | | .foregroundStyle(.white.opacity(0.84)) |
| | | .multilineTextAlignment(.leading) |
| | | .fixedSize(horizontal: false, vertical: true) |
| | | .frame(maxWidth: .infinity, alignment: .leading) |
| | | |
| | | Button { |
| | | doNotRemind.toggle() |
| | | } label: { |
| | | HStack(spacing: 10) { |
| | | ZStack { |
| | | RoundedRectangle(cornerRadius: 4, style: .continuous) |
| | | .fill(doNotRemind ? Color.accentColor : Color.white.opacity(0.10)) |
| | | RoundedRectangle(cornerRadius: 4, style: .continuous) |
| | | .stroke(Color.white.opacity(0.92), lineWidth: 1.6) |
| | | if doNotRemind { |
| | | Image(systemName: "checkmark") |
| | | .font(.system(size: 12, weight: .bold)) |
| | | .foregroundStyle(.white) |
| | | } |
| | | } |
| | | .frame(width: 18, height: 18) |
| | | |
| | | Text(doNotRemindTitle) |
| | | .font(.system(size: 13, weight: .medium)) |
| | | .foregroundStyle(.white.opacity(0.82)) |
| | | .lineLimit(2) |
| | | .multilineTextAlignment(.leading) |
| | | } |
| | | .contentShape(Rectangle()) |
| | | } |
| | | .buttonStyle(.plain) |
| | | |
| | | HStack { |
| | | Spacer(minLength: 0) |
| | | |
| | | Button(action: onConfirm) { |
| | | Text(confirmTitle) |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .foregroundStyle(.white) |
| | | .frame(minWidth: 96) |
| | | .frame(height: 32) |
| | | .padding(.horizontal, 10) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .fill(Color.accentColor) |
| | | ) |
| | | } |
| | | .buttonStyle(.plain) |
| | | } |
| | | } |
| | | .padding(.horizontal, 24) |
| | | .padding(.vertical, 20) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 18, style: .continuous) |
| | | .fill(Color.black.opacity(0.92)) |
| | | .shadow(color: .black.opacity(0.34), radius: 24, y: 16) |
| | | .shadow(color: .black.opacity(0.18), radius: 8, y: 3) |
| | | ) |
| | | .onExitCommand(perform: onCancel) |
| | | } |
| | | } |
| | | |
| | | private struct UsageTipsCloseReminderSettingsPreview: View { |
| | | let callout: String |
| | | |
| | | var body: some View { |
| | | VStack(alignment: .leading, spacing: 10) { |
| | | HStack(spacing: 6) { |
| | | Circle().fill(Color.red.opacity(0.78)).frame(width: 10, height: 10) |
| | | Circle().fill(Color.gray.opacity(0.45)).frame(width: 10, height: 10) |
| | | Circle().fill(Color.gray.opacity(0.36)).frame(width: 10, height: 10) |
| | | Text(verbatim: "TagLauncher Settings") |
| | | .font(.system(size: 11, weight: .semibold)) |
| | | .foregroundStyle(Color.black.opacity(0.62)) |
| | | .padding(.leading, 6) |
| | | Spacer() |
| | | } |
| | | |
| | | HStack(spacing: 18) { |
| | | previewTab(systemImage: "globe", title: tr("settings.language"), active: false) |
| | | previewTab(systemImage: "gearshape", title: tr("settings.general"), active: true) |
| | | previewTab(systemImage: "keyboard", title: tr("quickSearch.hotkeys"), active: false) |
| | | previewTab(systemImage: "tag", title: tr("settings.tags"), active: false) |
| | | previewTab(systemImage: "externaldrive.fill", title: tr("settings.data"), active: false) |
| | | previewTab(systemImage: "info.circle", title: tr("settings.about"), active: false) |
| | | } |
| | | .frame(maxWidth: .infinity, alignment: .center) |
| | | .padding(.vertical, 8) |
| | | |
| | | HStack(spacing: 12) { |
| | | previewCheckbox(title: tr("settings.launchAtLogin"), highlighted: false) |
| | | previewCheckbox(title: tr("settings.showInDock"), highlighted: false) |
| | | previewCheckbox(title: tr("settings.hideAppNames"), highlighted: false) |
| | | previewCheckbox(title: tr("settings.hideUsageTips"), highlighted: true) |
| | | } |
| | | .padding(10) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 10, style: .continuous) |
| | | .fill(Color.white.opacity(0.84)) |
| | | ) |
| | | |
| | | HStack(spacing: 8) { |
| | | Image(systemName: "arrow.up.left") |
| | | .font(.system(size: 12, weight: .bold)) |
| | | .foregroundStyle(Color.accentColor) |
| | | Text(callout) |
| | | .font(.system(size: 11, weight: .semibold)) |
| | | .foregroundStyle(Color.accentColor) |
| | | .lineLimit(2) |
| | | .fixedSize(horizontal: false, vertical: true) |
| | | } |
| | | .frame(maxWidth: .infinity, alignment: .trailing) |
| | | } |
| | | .padding(14) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 14, style: .continuous) |
| | | .fill( |
| | | LinearGradient( |
| | | colors: [ |
| | | Color.white.opacity(0.98), |
| | | Color(red: 0.93, green: 0.96, blue: 1.0).opacity(0.96) |
| | | ], |
| | | startPoint: .topLeading, |
| | | endPoint: .bottomTrailing |
| | | ) |
| | | ) |
| | | ) |
| | | .overlay( |
| | | RoundedRectangle(cornerRadius: 14, style: .continuous) |
| | | .stroke(Color.white.opacity(0.64), lineWidth: 1) |
| | | ) |
| | | } |
| | | |
| | | private func previewTab(systemImage: String, title: String, active: Bool) -> some View { |
| | | VStack(spacing: 4) { |
| | | Image(systemName: systemImage) |
| | | .font(.system(size: 18, weight: .semibold)) |
| | | Text(title) |
| | | .font(.system(size: 9, weight: .semibold)) |
| | | .lineLimit(1) |
| | | .minimumScaleFactor(0.62) |
| | | } |
| | | .foregroundStyle(active ? Color.accentColor : Color.gray.opacity(0.82)) |
| | | .frame(width: 70, height: 48) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 9, style: .continuous) |
| | | .fill(active ? Color.accentColor.opacity(0.12) : Color.clear) |
| | | ) |
| | | } |
| | | |
| | | private func previewCheckbox(title: String, highlighted: Bool) -> some View { |
| | | HStack(spacing: 6) { |
| | | ZStack { |
| | | RoundedRectangle(cornerRadius: 4, style: .continuous) |
| | | .fill(highlighted ? Color.accentColor : Color.gray.opacity(0.24)) |
| | | Image(systemName: "checkmark") |
| | | .font(.system(size: 9, weight: .bold)) |
| | | .foregroundStyle(.white) |
| | | } |
| | | .frame(width: 16, height: 16) |
| | | |
| | | Text(title) |
| | | .font(.system(size: 10, weight: highlighted ? .bold : .semibold)) |
| | | .foregroundStyle(Color.black.opacity(0.72)) |
| | | .lineLimit(1) |
| | | .minimumScaleFactor(0.58) |
| | | } |
| | | .padding(.horizontal, 8) |
| | | .frame(height: 30) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .fill(highlighted ? Color.accentColor.opacity(0.12) : Color.clear) |
| | | ) |
| | | .overlay( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .stroke(highlighted ? Color.accentColor.opacity(0.72) : Color.clear, lineWidth: 1.5) |
| | | ) |
| | | } |
| | | } |