fix: capitalize Terebi application name

This commit is contained in:
2026-10-18 20:05:12 +02:00
parent 0e860b2ef6
commit 2e61bd7864
5 changed files with 22 additions and 21 deletions
+5 -5
View File
@@ -47,11 +47,11 @@ release:
install: release install: release
mkdir -p "$(APPDIR)" "$(PREFIX)/bin" mkdir -p "$(APPDIR)" "$(PREFIX)/bin"
rm -f "$(PREFIX)/lib/terebi/terebi" rm -f "$(PREFIX)/lib/terebi/terebi"
rm -rf "$(PREFIX)/lib/terebi/terebi.app" "$(APPDIR)/terebi.app" rm -rf "$(PREFIX)/lib/terebi/terebi.app" "$(APPDIR)/terebi.app" "$(APPDIR)/Terebi.app"
cp -R ".build/release/terebi.app" "$(APPDIR)/terebi.app" cp -R ".build/release/terebi.app" "$(APPDIR)/Terebi.app"
ln -sfn "$$(cd "$(APPDIR)" && pwd)/terebi.app/Contents/MacOS/terebi-cli" "$(PREFIX)/bin/terebi" ln -sfn "$$(cd "$(APPDIR)" && pwd)/Terebi.app/Contents/MacOS/terebi-cli" "$(PREFIX)/bin/terebi"
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "$(APPDIR)/terebi.app" /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "$(APPDIR)/Terebi.app"
mdimport "$(APPDIR)/terebi.app" mdimport "$(APPDIR)/Terebi.app"
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p "$@" mkdir -p "$@"
+1 -1
View File
@@ -25,7 +25,7 @@ export PATH="$HOME/.local/bin:$PATH"
terebi --help terebi --help
``` ```
Installation builds a release, places `terebi.app` in `~/Applications`, registers it with Launch Services, and requests Spotlight indexing. The CLI symlink is `~/.local/bin/terebi`; any old app under `~/.local/lib/terebi` is removed. Quit running players before updating. Installation builds a release, places `Terebi.app` in `~/Applications`, registers it with Launch Services, and requests Spotlight indexing. The application display name is **Terebi**; the CLI remains `~/.local/bin/terebi`. Any old app under `~/.local/lib/terebi` or lowercase installed bundle is removed. Quit running players before updating.
Use `make install APPDIR="/Applications"` to change the app directory (it must be writable), `PREFIX="/custom/path"` to change the CLI prefix (`bin/terebi`), or both. Use `make release` for just `.build/release/terebi.app`. Use `make install APPDIR="/Applications"` to change the app directory (it must be writable), `PREFIX="/custom/path"` to change the CLI prefix (`bin/terebi`), or both. Use `make release` for just `.build/release/terebi.app`.
+2 -1
View File
@@ -4,7 +4,8 @@
<dict> <dict>
<key>CFBundleExecutable</key><string>terebi</string> <key>CFBundleExecutable</key><string>terebi</string>
<key>CFBundleIdentifier</key><string>local.personal.terebi</string> <key>CFBundleIdentifier</key><string>local.personal.terebi</string>
<key>CFBundleName</key><string>terebi</string> <key>CFBundleName</key><string>Terebi</string>
<key>CFBundleDisplayName</key><string>Terebi</string>
<key>CFBundlePackageType</key><string>APPL</string> <key>CFBundlePackageType</key><string>APPL</string>
<key>CFBundleShortVersionString</key><string>0.1</string> <key>CFBundleShortVersionString</key><string>0.1</string>
<key>LSMinimumSystemVersion</key><string>15.0</string> <key>LSMinimumSystemVersion</key><string>15.0</string>
+3 -3
View File
@@ -12,10 +12,10 @@ enum TerebiBootstrap {
let payload = app.appendingPathComponent("Contents/Frameworks/libterebi-player.dylib") let payload = app.appendingPathComponent("Contents/Frameworks/libterebi-player.dylib")
guard let library = dlopen(payload.path, RTLD_NOW | RTLD_LOCAL) else { guard let library = dlopen(payload.path, RTLD_NOW | RTLD_LOCAL) else {
let detail = dlerror().map { String(cString: $0) } ?? "The dynamic loader could not load the player." let detail = dlerror().map { String(cString: $0) } ?? "The dynamic loader could not load the player."
fail("Could not load the player: \(detail)\n\nPlayer library: \(payload.path)\nRebuild and reinstall terebi.") fail("Could not load the player: \(detail)\n\nPlayer library: \(payload.path)\nRebuild and reinstall Terebi.")
} }
guard let entry = dlsym(library, "terebi_app_main") else { guard let entry = dlsym(library, "terebi_app_main") else {
fail("The player library is missing its application entry point. Rebuild and reinstall terebi.") fail("The player library is missing its application entry point. Rebuild and reinstall Terebi.")
} }
// Keep the declared app executable alive so LaunchServices retains its identity. // Keep the declared app executable alive so LaunchServices retains its identity.
typealias PlayerMain = @convention(c) () -> Void typealias PlayerMain = @convention(c) () -> Void
@@ -29,7 +29,7 @@ enum TerebiBootstrap {
application.activate(ignoringOtherApps: true) application.activate(ignoringOtherApps: true)
let alert = NSAlert() let alert = NSAlert()
alert.alertStyle = .critical alert.alertStyle = .critical
alert.messageText = "terebi could not start" alert.messageText = "Terebi could not start"
alert.informativeText = message alert.informativeText = message
alert.addButton(withTitle: "Quit") alert.addButton(withTitle: "Quit")
alert.runModal() alert.runModal()
+11 -11
View File
@@ -220,7 +220,7 @@ final class PlayerModel: ObservableObject {
guard canCast, let source = currentMedia, let handle else { return } guard canCast, let source = currentMedia, let handle else { return }
cancelYouTubeResolution() cancelYouTubeResolution()
commandError = nil commandError = nil
casting.start(to: device, source: source, title: fileName ?? "terebi", subtitle: selectedSubtitle, casting.start(to: device, source: source, title: fileName ?? "Terebi", subtitle: selectedSubtitle,
handle: handle, snapshot: state, playing: playing ?? effectivePlaying, handle: handle, snapshot: state, playing: playing ?? effectivePlaying,
volume: volume, audibleVolume: lastAudibleVolume) volume: volume, audibleVolume: lastAudibleVolume)
revealControls() revealControls()
@@ -555,7 +555,7 @@ final class PlayerModel: ObservableObject {
isSeeking = false isSeeking = false
seekPosition = 0 seekPosition = 0
window?.representedURL = source.url window?.representedURL = source.url
window?.title = fileName ?? "terebi" window?.title = fileName ?? "Terebi"
revealControls() revealControls()
systemPlayback?.update() systemPlayback?.update()
} }
@@ -711,7 +711,7 @@ final class PlayerModel: ObservableObject {
commandError = nil commandError = nil
isSeeking = false isSeeking = false
window?.representedURL = nil window?.representedURL = nil
window?.title = "terebi" window?.title = "Terebi"
revealControls() revealControls()
systemPlayback?.update() systemPlayback?.update()
} }
@@ -762,7 +762,7 @@ final class PlayerModel: ObservableObject {
func attachWindow(_ window: NSWindow) { func attachWindow(_ window: NSWindow) {
guard self.window !== window else { return } guard self.window !== window else { return }
self.window = window self.window = window
window.title = fileName ?? "terebi" window.title = fileName ?? "Terebi"
window.contentMinSize = NSSize(width: 400, height: 240) window.contentMinSize = NSSize(width: 400, height: 240)
compactWindow.normalVideoLayout = { [weak self] in compactWindow.normalVideoLayout = { [weak self] in
guard let self, self.showsQueue, self.state.has_video else { return nil } guard let self, self.showsQueue, self.state.has_video else { return nil }
@@ -1978,7 +1978,7 @@ private struct PlayerContent: View {
private func compactTitleLabel(progress: String?, constrained: Bool) -> some View { private func compactTitleLabel(progress: String?, constrained: Bool) -> some View {
HStack(spacing: 0) { HStack(spacing: 0) {
Text(model.fileName ?? "terebi") Text(model.fileName ?? "Terebi")
.lineLimit(1) .lineLimit(1)
.truncationMode(.tail) .truncationMode(.tail)
.frame(minWidth: 0, maxWidth: constrained ? .infinity : nil, alignment: .leading) .frame(minWidth: 0, maxWidth: constrained ? .infinity : nil, alignment: .leading)
@@ -2069,11 +2069,11 @@ private struct PlayerContent: View {
} else { } else {
Image(systemName: "play.rectangle.fill").font(.system(size: 14)) Image(systemName: "play.rectangle.fill").font(.system(size: 14))
} }
Text(model.fileName ?? "terebi") Text(model.fileName ?? "Terebi")
.font(.system(size: 13, weight: .semibold)) .font(.system(size: 13, weight: .semibold))
.lineLimit(1) .lineLimit(1)
.truncationMode(.tail) .truncationMode(.tail)
.help(model.fileName ?? "terebi") .help(model.fileName ?? "Terebi")
} }
.padding(.horizontal, 8) .padding(.horizontal, 8)
.frame(height: 24) .frame(height: 24)
@@ -2491,7 +2491,7 @@ private struct PlayerContent: View {
.foregroundStyle(Color(SunsetPalette.accent)) .foregroundStyle(Color(SunsetPalette.accent))
.accessibilityHidden(true) .accessibilityHidden(true)
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
Text("terebi").font(.system(size: 20, weight: .semibold)) Text("Terebi").font(.system(size: 20, weight: .semibold))
.foregroundStyle(Color(SunsetPalette.text)) .foregroundStyle(Color(SunsetPalette.text))
Text("Open media to get started") Text("Open media to get started")
.font(.callout) .font(.callout)
@@ -2603,7 +2603,7 @@ private struct PlayerContent: View {
} }
.font(.system(size: 11, weight: .medium)) .font(.system(size: 11, weight: .medium))
.accessibilityElement(children: .combine) .accessibilityElement(children: .combine)
.help((model.fileName ?? "terebi") + (progress.map { " · \($0)" } ?? "")) .help((model.fileName ?? "Terebi") + (progress.map { " · \($0)" } ?? ""))
.padding(.horizontal, 8) .padding(.horizontal, 8)
.frame(height: 28) .frame(height: 28)
.background(PlayerGlass(cornerRadius: 10).clipShape(RoundedRectangle(cornerRadius: 10)).allowsHitTesting(false)) .background(PlayerGlass(cornerRadius: 10).clipShape(RoundedRectangle(cornerRadius: 10)).allowsHitTesting(false))
@@ -2848,7 +2848,7 @@ struct TerebiApp: App {
@StateObject private var model = PlayerModel.shared @StateObject private var model = PlayerModel.shared
var body: some Scene { var body: some Scene {
Window("\(model.fileName ?? "terebi")", id: "terebi") { Window("\(model.fileName ?? "Terebi")", id: "terebi") {
PlayerContent(model: model) PlayerContent(model: model)
.focusedSceneObject(model) .focusedSceneObject(model)
} }
@@ -2874,7 +2874,7 @@ public func terebiAppMain() {
NSApp.activate(ignoringOtherApps: true) NSApp.activate(ignoringOtherApps: true)
let alert = NSAlert() let alert = NSAlert()
alert.alertStyle = .critical alert.alertStyle = .critical
alert.messageText = "Could not load terebi configuration" alert.messageText = "Could not load Terebi configuration"
alert.informativeText = error.localizedDescription alert.informativeText = error.localizedDescription
alert.runModal() alert.runModal()
exit(78) exit(78)