ice: new port

https://icemenubar.app/
This commit is contained in:
Herby Gillot
2026-04-09 03:59:12 -04:00
parent c8baa073be
commit 2c26db45dd
2 changed files with 290 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
PortSystem 1.0
PortGroup xcode 1.0
PortGroup github 1.0
github.setup jordanbaird Ice 0.11.12
github.tarball_from archive
revision 0
homepage https://icemenubar.app/
categories aqua
license GPL-3
platforms {macosx >= 14}
maintainers {gmail.com:herby.gillot @herbygillot} \
openmaintainer
description Powerful menu bar manager for macOS
long_description \
Ice is a powerful menu bar management tool for macOS. While its primary \
function is hiding and showing menu bar items, it offers a wide range of \
features to manage the menu bar. Items can be hidden or shown on demand, \
rearranged via drag-and-drop, and searched. The menu bar appearance can \
also be fully customized.
checksums rmd160 c02a7a7f7839254c5cac1ffa941abefcb43378a2 \
sha256 6de28150c65d03bc17f80dc745eff15680903679a4dfe3b4bc88d46651761bb3 \
size 16700295
patchfiles patch-disable-sparkle.diff
post-patch {
# Remove Sparkle feed URL and public key from Info.plist
set plist ${worksrcpath}/Ice/Info.plist
system "/usr/libexec/PlistBuddy -c 'Delete :SUFeedURL' ${plist}"
system "/usr/libexec/PlistBuddy -c 'Delete :SUPublicEDKey' ${plist}"
}
xcode.scheme Ice
xcode.configuration Release
# SPM generates sandbox profile temp files outside ${workpath}, which the
# MacPorts build sandbox blocks from being read, causing sandbox_apply to fail.
# Redirect all of Xcode's working state into ${workpath} to keep everything
# within the sandbox-allowed tree.
build.pre_args-append -derivedDataPath ${workpath}/derived-data \
-clonedSourcePackagesDirPath ${workpath}/spm-packages
build.env-append TMPDIR=${workpath}/tmp \
HOME=${workpath}/home
pre-build {
file mkdir ${workpath}/tmp
file mkdir ${workpath}/home/Library/Caches
# SPM sandboxes its manifest-loading subprocesses via sandbox-exec, but
# macOS rejects nested sandbox_apply calls when the process is already
# sandboxed by MacPorts. Allow sandbox-exec to run without inheriting
# the MacPorts profile so it can apply its own profile successfully.
append portsandbox_profile " (allow process-exec (literal \"/usr/bin/sandbox-exec\") (with no-profile))"
}
xcode.build.settings-append \
SDKROOT=macosx \
DEVELOPMENT_TEAM= \
CODE_SIGN_IDENTITY= \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_ENTITLEMENTS= \
ENABLE_USER_SCRIPT_SANDBOXING=NO \
OTHER_SWIFT_FLAGS='-Xfrontend -disable-availability-checking'
destroot {
copy ${worksrcpath}/build/${xcode.configuration}/Ice.app \
${destroot}${applications_dir}/Ice.app
}
+213
View File
@@ -0,0 +1,213 @@
--- Ice/Updates/UpdatesManager.swift
+++ Ice/Updates/UpdatesManager.swift
@@ -3,7 +3,6 @@
// Ice
//
-import Sparkle
import SwiftUI
/// Manager for app updates.
@@ -18,39 +17,11 @@
/// The shared app state.
private(set) weak var appState: AppState?
- /// The underlying updater controller.
- private(set) lazy var updaterController = SPUStandardUpdaterController(
- startingUpdater: true,
- updaterDelegate: self,
- userDriverDelegate: self
- )
-
- /// The underlying updater.
- var updater: SPUUpdater {
- updaterController.updater
- }
-
/// A Boolean value that indicates whether to automatically check for updates.
- var automaticallyChecksForUpdates: Bool {
- get {
- updater.automaticallyChecksForUpdates
- }
- set {
- objectWillChange.send()
- updater.automaticallyChecksForUpdates = newValue
- }
- }
+ var automaticallyChecksForUpdates: Bool = false
/// A Boolean value that indicates whether to automatically download updates.
- var automaticallyDownloadsUpdates: Bool {
- get {
- updater.automaticallyDownloadsUpdates
- }
- set {
- objectWillChange.send()
- updater.automaticallyDownloadsUpdates = newValue
- }
- }
+ var automaticallyDownloadsUpdates: Bool = false
/// Creates an updates manager with the given app state.
init(appState: AppState) {
@@ -59,87 +30,11 @@
}
/// Sets up the manager.
- func performSetup() {
- _ = updaterController
- configureCancellables()
- }
+ func performSetup() { }
- /// Configures the internal observers for the manager.
- private func configureCancellables() {
- updater.publisher(for: \.canCheckForUpdates)
- .assign(to: &$canCheckForUpdates)
- updater.publisher(for: \.lastUpdateCheckDate)
- .assign(to: &$lastUpdateCheckDate)
- }
-
/// Checks for app updates.
- @objc func checkForUpdates() {
- #if DEBUG
- // Checking for updates hangs in debug mode.
- let alert = NSAlert()
- alert.messageText = "Checking for updates is not supported in debug mode."
- alert.runModal()
- #else
- guard let appState else {
- return
- }
- // Activate the app in case an alert needs to be displayed.
- appState.activate(withPolicy: .regular)
- appState.openSettingsWindow()
- updater.checkForUpdates()
- #endif
- }
+ @objc func checkForUpdates() { }
}
-// MARK: UpdatesManager: SPUUpdaterDelegate
-extension UpdatesManager: @preconcurrency SPUUpdaterDelegate {
- func updater(_ updater: SPUUpdater, willScheduleUpdateCheckAfterDelay delay: TimeInterval) {
- guard let appState else {
- return
- }
- appState.userNotificationManager.requestAuthorization()
- }
-}
-
-// MARK: UpdatesManager: SPUStandardUserDriverDelegate
-extension UpdatesManager: @preconcurrency SPUStandardUserDriverDelegate {
- var supportsGentleScheduledUpdateReminders: Bool { true }
-
- func standardUserDriverShouldHandleShowingScheduledUpdate(
- _ update: SUAppcastItem,
- andInImmediateFocus immediateFocus: Bool
- ) -> Bool {
- if NSApp.isActive {
- return immediateFocus
- } else {
- return false
- }
- }
-
- func standardUserDriverWillHandleShowingUpdate(
- _ handleShowingUpdate: Bool,
- forUpdate update: SUAppcastItem,
- state: SPUUserUpdateState
- ) {
- guard let appState else {
- return
- }
- if !state.userInitiated {
- appState.userNotificationManager.addRequest(
- with: .updateCheck,
- title: "A new update is available",
- body: "Version \(update.displayVersionString) is now available"
- )
- }
- }
-
- func standardUserDriverDidReceiveUserAttention(forUpdate update: SUAppcastItem) {
- guard let appState else {
- return
- }
- appState.userNotificationManager.removeDeliveredNotifications(with: [.updateCheck])
- }
-}
-
// MARK: UpdatesManager: BindingExposable
extension UpdatesManager: BindingExposable { }
--- Ice/Settings/SettingsPanes/UpdatesSettingsPane.swift
+++ Ice/Settings/SettingsPanes/UpdatesSettingsPane.swift
@@ -6,66 +6,8 @@
import SwiftUI
struct UpdatesSettingsPane: View {
- @EnvironmentObject var appState: AppState
-
- private var updatesManager: UpdatesManager {
- appState.updatesManager
- }
-
- private var lastUpdateCheckString: String {
- if let date = updatesManager.lastUpdateCheckDate {
- date.formatted(date: .abbreviated, time: .standard)
- } else {
- "Never"
- }
- }
-
var body: some View {
- IceForm {
- IceSection {
- automaticallyCheckForUpdates
- automaticallyDownloadUpdates
- }
- if updatesManager.canCheckForUpdates {
- IceSection {
- checkForUpdates
- }
- }
- }
+ Text("Updates are managed by MacPorts.")
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
}
-
- @ViewBuilder
- private var automaticallyCheckForUpdates: some View {
- Toggle(
- "Automatically check for updates",
- isOn: updatesManager.bindings.automaticallyChecksForUpdates
- )
- }
-
- @ViewBuilder
- private var automaticallyDownloadUpdates: some View {
- Toggle(
- "Automatically download updates",
- isOn: updatesManager.bindings.automaticallyDownloadsUpdates
- )
- }
-
- @ViewBuilder
- private var checkForUpdates: some View {
- HStack {
- Button("Check for Updates…") {
- updatesManager.checkForUpdates()
- }
- .controlSize(.large)
-
- Spacer()
-
- HStack(spacing: 2) {
- Text("Last checked:")
- Text(lastUpdateCheckString)
- }
- .lineLimit(1)
- .font(.caption)
- }
- }
}