-
Notifications
You must be signed in to change notification settings - Fork 1
fix(desktop): fix yt-dlp PATH resolution and surface transcribe errors #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,7 @@ struct ContentView: View { | |||||||||||||||||||||||||||||||||||||||
| @State private var channelBusyMessage: String? | ||||||||||||||||||||||||||||||||||||||||
| @State private var exhaustedChannels: Set<String> = [] | ||||||||||||||||||||||||||||||||||||||||
| @State private var transcribingPostID: DashboardPost.ID? | ||||||||||||||||||||||||||||||||||||||||
| @State private var transcribeError: String? | ||||||||||||||||||||||||||||||||||||||||
| @State private var credentialForm = CredentialForm() | ||||||||||||||||||||||||||||||||||||||||
| @State private var credentialNotice: Notice? | ||||||||||||||||||||||||||||||||||||||||
| @State private var pendingDeleteCredential: PlatformCredential? | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -406,45 +407,54 @@ struct ContentView: View { | |||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| private func readerTopBar(_ post: DashboardPost) -> some View { | ||||||||||||||||||||||||||||||||||||||||
| HStack(alignment: .top, spacing: 16) { | ||||||||||||||||||||||||||||||||||||||||
| VStack(alignment: .leading, spacing: 8) { | ||||||||||||||||||||||||||||||||||||||||
| HStack(spacing: 8) { | ||||||||||||||||||||||||||||||||||||||||
| platformBadge(post.platform) | ||||||||||||||||||||||||||||||||||||||||
| Text(post.source ?? post.author) | ||||||||||||||||||||||||||||||||||||||||
| .font(.caption.weight(.medium)) | ||||||||||||||||||||||||||||||||||||||||
| .foregroundStyle(.secondary) | ||||||||||||||||||||||||||||||||||||||||
| .lineLimit(1) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Text(post.displayTitle) | ||||||||||||||||||||||||||||||||||||||||
| .font(.title2.weight(.semibold)) | ||||||||||||||||||||||||||||||||||||||||
| .lineSpacing(2) | ||||||||||||||||||||||||||||||||||||||||
| .lineLimit(2) | ||||||||||||||||||||||||||||||||||||||||
| .textSelection(.enabled) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Spacer(minLength: 16) | ||||||||||||||||||||||||||||||||||||||||
| HStack(spacing: 10) { | ||||||||||||||||||||||||||||||||||||||||
| if post.platform == "youtube", (post.contentMarkdown ?? "").isEmpty { | ||||||||||||||||||||||||||||||||||||||||
| Button { | ||||||||||||||||||||||||||||||||||||||||
| transcribe(post) | ||||||||||||||||||||||||||||||||||||||||
| } label: { | ||||||||||||||||||||||||||||||||||||||||
| Label( | ||||||||||||||||||||||||||||||||||||||||
| transcribeButtonTitle(post), | ||||||||||||||||||||||||||||||||||||||||
| systemImage: transcribingPostID == post.id ? "hourglass" : "captions.bubble" | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| VStack(alignment: .leading, spacing: 8) { | ||||||||||||||||||||||||||||||||||||||||
| HStack(alignment: .top, spacing: 16) { | ||||||||||||||||||||||||||||||||||||||||
| VStack(alignment: .leading, spacing: 8) { | ||||||||||||||||||||||||||||||||||||||||
| HStack(spacing: 8) { | ||||||||||||||||||||||||||||||||||||||||
| platformBadge(post.platform) | ||||||||||||||||||||||||||||||||||||||||
| Text(post.source ?? post.author) | ||||||||||||||||||||||||||||||||||||||||
| .font(.caption.weight(.medium)) | ||||||||||||||||||||||||||||||||||||||||
| .foregroundStyle(.secondary) | ||||||||||||||||||||||||||||||||||||||||
| .lineLimit(1) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .buttonStyle(.bordered) | ||||||||||||||||||||||||||||||||||||||||
| .disabled(transcribingPostID != nil) | ||||||||||||||||||||||||||||||||||||||||
| Text(post.displayTitle) | ||||||||||||||||||||||||||||||||||||||||
| .font(.title2.weight(.semibold)) | ||||||||||||||||||||||||||||||||||||||||
| .lineSpacing(2) | ||||||||||||||||||||||||||||||||||||||||
| .lineLimit(2) | ||||||||||||||||||||||||||||||||||||||||
| .textSelection(.enabled) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| readerModeToggle | ||||||||||||||||||||||||||||||||||||||||
| if let url = post.url { | ||||||||||||||||||||||||||||||||||||||||
| Button { | ||||||||||||||||||||||||||||||||||||||||
| NSWorkspace.shared.open(url) | ||||||||||||||||||||||||||||||||||||||||
| } label: { | ||||||||||||||||||||||||||||||||||||||||
| Label("열기", systemImage: "arrow.up.right") | ||||||||||||||||||||||||||||||||||||||||
| Spacer(minLength: 16) | ||||||||||||||||||||||||||||||||||||||||
| HStack(spacing: 10) { | ||||||||||||||||||||||||||||||||||||||||
| if post.platform == "youtube", (post.contentMarkdown ?? "").isEmpty { | ||||||||||||||||||||||||||||||||||||||||
| Button { | ||||||||||||||||||||||||||||||||||||||||
| transcribe(post) | ||||||||||||||||||||||||||||||||||||||||
| } label: { | ||||||||||||||||||||||||||||||||||||||||
| Label( | ||||||||||||||||||||||||||||||||||||||||
| transcribeButtonTitle(post), | ||||||||||||||||||||||||||||||||||||||||
| systemImage: transcribingPostID == post.id ? "hourglass" : "captions.bubble" | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .buttonStyle(.bordered) | ||||||||||||||||||||||||||||||||||||||||
| .disabled(transcribingPostID != nil) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| readerModeToggle | ||||||||||||||||||||||||||||||||||||||||
| if let url = post.url { | ||||||||||||||||||||||||||||||||||||||||
| Button { | ||||||||||||||||||||||||||||||||||||||||
| NSWorkspace.shared.open(url) | ||||||||||||||||||||||||||||||||||||||||
| } label: { | ||||||||||||||||||||||||||||||||||||||||
| Label("열기", systemImage: "arrow.up.right") | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .buttonStyle(.bordered) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .buttonStyle(.bordered) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| if let transcribeError { | ||||||||||||||||||||||||||||||||||||||||
| Text("전사 실패: \(transcribeError)") | ||||||||||||||||||||||||||||||||||||||||
| .font(.caption) | ||||||||||||||||||||||||||||||||||||||||
| .foregroundStyle(Color.red) | ||||||||||||||||||||||||||||||||||||||||
| .textSelection(.enabled) | ||||||||||||||||||||||||||||||||||||||||
| .lineLimit(3) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+451
to
+457
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .padding(.horizontal, 30) | ||||||||||||||||||||||||||||||||||||||||
| .padding(.vertical, 18) | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1258,13 +1268,14 @@ struct ContentView: View { | |||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| transcribingPostID = post.id | ||||||||||||||||||||||||||||||||||||||||
| transcribeError = nil | ||||||||||||||||||||||||||||||||||||||||
| Task { @MainActor in | ||||||||||||||||||||||||||||||||||||||||
| do { | ||||||||||||||||||||||||||||||||||||||||
| _ = try await runSkim(["youtube-transcribe", url.absoluteString]) | ||||||||||||||||||||||||||||||||||||||||
| reloadChannelPosts() | ||||||||||||||||||||||||||||||||||||||||
| loadDashboard() | ||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||
| sourceMessage = Notice(text: localizedError(error), isError: true) | ||||||||||||||||||||||||||||||||||||||||
| transcribeError = localizedError(error) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1271
to
1279
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 전사 시작 시 해당 포스트의 에러를 초기화하고, 실패 시 해당 포스트 ID를 키로 하여 에러 메시지를 저장하도록 수정합니다.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| transcribingPostID = nil | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1285,6 +1296,13 @@ struct ContentView: View { | |||||||||||||||||||||||||||||||||||||||
| process.executableURL = URL(fileURLWithPath: uv) | ||||||||||||||||||||||||||||||||||||||||
| process.arguments = ["run", "skim"] + arguments | ||||||||||||||||||||||||||||||||||||||||
| process.currentDirectoryURL = workspace | ||||||||||||||||||||||||||||||||||||||||
| // Finder/LaunchServices로 띄운 앱은 셸 프로필(PATH)을 물려받지 않아 | ||||||||||||||||||||||||||||||||||||||||
| // yt-dlp/ffmpeg 같은 ~/.local/bin, Homebrew 도구를 못 찾는다. | ||||||||||||||||||||||||||||||||||||||||
| var environment = ProcessInfo.processInfo.environment | ||||||||||||||||||||||||||||||||||||||||
| let extraPaths = ["/opt/homebrew/bin", "/usr/local/bin", "\(NSHomeDirectory())/.local/bin"] | ||||||||||||||||||||||||||||||||||||||||
| let existingPath = environment["PATH"] ?? "/usr/bin:/bin:/usr/sbin:/sbin" | ||||||||||||||||||||||||||||||||||||||||
| environment["PATH"] = (extraPaths + [existingPath]).joined(separator: ":") | ||||||||||||||||||||||||||||||||||||||||
| process.environment = environment | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1301
to
+1305
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기에는 두 가지 중요한 개선 사항이 있습니다:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| let pipe = Pipe() | ||||||||||||||||||||||||||||||||||||||||
| process.standardOutput = pipe | ||||||||||||||||||||||||||||||||||||||||
| process.standardError = pipe | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재
transcribeError는 단일 글로벌@State변수로 선언되어 있습니다. 이 경우 특정 포스트의 전사가 실패한 후 다른 포스트를 선택하더라도 이전 포스트의 에러 메시지가 상단바에 계속 표시되는 UX 버그가 발생합니다.transcribeError를[DashboardPost.ID: String]딕셔너리 형태로 변경하여 에러 메시지를 각 포스트별로 격리하는 것을 권장합니다.