feat(macos): add proper macOS wrapper app (#1290)
Still missing build process + assembly of bundle
161
.github/workflows/build-and-release-binary.yml
vendored
@@ -43,10 +43,6 @@ jobs:
|
||||
target: linux-x64
|
||||
- name: ubuntu-22.04-arm
|
||||
target: linux-arm64
|
||||
- name: macos-13
|
||||
target: macos-x64
|
||||
- name: macos-14
|
||||
target: macos-arm64
|
||||
- name: windows-latest
|
||||
target: win-x64
|
||||
runs-on: ubuntu-latest
|
||||
@@ -71,40 +67,21 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: 'Create env file (release)'
|
||||
run: |
|
||||
touch .env
|
||||
echo TUNARR_EDGE_BUILD=false >> .env
|
||||
echo NODE_ENV=production >> .env
|
||||
echo TUNARR_BIND_ADDR=0.0.0.0 >> .env
|
||||
cat .env
|
||||
cp .env server/.env
|
||||
cp .env web/.env
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
- name: 'Create env file (edge)'
|
||||
- name: 'Create env file'
|
||||
run: |
|
||||
touch .env
|
||||
echo TUNARR_BUILD="$(git rev-parse --short ${{ github.sha }})" >> .env
|
||||
echo TUNARR_EDGE_BUILD=true >> .env
|
||||
echo TUNARR_EDGE_BUILD=${{github.ref == format('refs/heads/{0}', 'dev') && (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')}} >> .env
|
||||
echo NODE_ENV=production >> .env
|
||||
echo TUNARR_BIND_ADDR=0.0.0.0 >> .env
|
||||
grep -v '^#.*' .env >> $GITHUB_ENV
|
||||
cat .env
|
||||
cp .env server/.env
|
||||
cp .env web/.env
|
||||
if: github.ref == format('refs/heads/{0}', 'dev') && (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
|
||||
|
||||
- name: Bundle web
|
||||
run: pnpm turbo bundle --filter=@tunarr/web
|
||||
|
||||
# Install ldid for adhoc signing of macos ARM binaries. PKG should take
|
||||
# care of this.
|
||||
- name: Install ldid
|
||||
uses: MOZGIII/install-ldid-action@v1
|
||||
with:
|
||||
tag: v2.1.5-procursus2
|
||||
if: matrix.os.target == 'macos-arm64'
|
||||
|
||||
- name: Build Executable
|
||||
run: pnpm turbo make-bin -- --target ${{matrix.os.target}}
|
||||
|
||||
@@ -124,3 +101,135 @@ jobs:
|
||||
files: |
|
||||
./server/bin/tunarr-*
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
build-mac:
|
||||
needs: typecheck
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- name: macos-13
|
||||
target: macos-x64
|
||||
runner: macos-13
|
||||
- name: macos-14
|
||||
target: macos-arm64
|
||||
runner: macos-latest
|
||||
runs-on: ${{matrix.os.runner}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4 # Checkout code from repository
|
||||
|
||||
- uses: ilammy/setup-nasm@v1
|
||||
|
||||
- name: Use Latest Corepack
|
||||
run: |
|
||||
npm install -g corepack@latest
|
||||
corepack enable && corepack enable pnpm
|
||||
pnpm --version
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22.13.0
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
pnpm install
|
||||
brew install jq
|
||||
|
||||
- name: Import Code-Signing Certificates
|
||||
uses: Apple-Actions/import-codesign-certs@v2
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE_P12_BASE64 }}
|
||||
p12-password: ${{ secrets.APPLE_CERTIFICATE_P12_PASSWORD }}
|
||||
|
||||
- name: 'Create env file'
|
||||
run: |
|
||||
touch .env
|
||||
echo TUNARR_BUILD="$(git rev-parse --short ${{ github.sha }})" >> .env
|
||||
echo TUNARR_EDGE_BUILD=${{github.ref == format('refs/heads/{0}', 'dev') && (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')}} >> .env
|
||||
echo NODE_ENV=production >> .env
|
||||
echo TUNARR_BIND_ADDR=0.0.0.0 >> .env
|
||||
|
||||
tunarr_version="$(jq -r .version package.json)"
|
||||
if [[ "$TUNARR_EDGE_BUILD" == "true" || "$TUNARR_EDGE_BUILD" == "1" ]]; then
|
||||
is_edge_build=true
|
||||
else
|
||||
is_edge_build=false
|
||||
fi
|
||||
|
||||
if [[ -n "$TUNARR_BUILD" && "$TUNARR_EDGE_BUILD" == true ]]; then
|
||||
tunarr_version+="-${build}"
|
||||
fi
|
||||
echo "TUNARR_VERSION=${tunarr_version}" >> $GITHUB_ENV
|
||||
release_name="Tunarr-${tunarr_version}-${{ matrix.os.target }}"
|
||||
echo "RELEASE_NAME=${release_name}" >> $GITHUB_ENV
|
||||
|
||||
grep -v '^#.*' .env >> $GITHUB_ENV
|
||||
cat .env
|
||||
cp .env server/.env
|
||||
cp .env web/.env
|
||||
|
||||
- name: Bundle web
|
||||
run: pnpm turbo bundle --filter=@tunarr/web
|
||||
|
||||
- name: Build Executable
|
||||
run: pnpm turbo make-bin -- --target ${{matrix.os.target}}
|
||||
|
||||
- name: Bundle
|
||||
shell: bash
|
||||
run: |
|
||||
brew install coreutils
|
||||
plutil -replace CFBundleShortVersionString -string "$TUNARR_VERSION" macos/Tunarr/Tunarr/Info.plist
|
||||
plutil -replace CFBundleVersion -string "$TUNARR_VERSION" macos/Tunarr/Tunarr/Info.plist
|
||||
scripts/bundle-macos.sh
|
||||
|
||||
- name: Sign
|
||||
shell: bash
|
||||
run: scripts/sign-macos.sh
|
||||
|
||||
- name: Create DMG
|
||||
shell: bash
|
||||
run: |
|
||||
brew install create-dmg
|
||||
create-dmg \
|
||||
--volname "Tunarr" \
|
||||
--volicon "design/Tunarr.icns" \
|
||||
--window-pos 200 120 \
|
||||
--window-size 800 400 \
|
||||
--icon-size 100 \
|
||||
--icon "Tunarr.app" 200 190 \
|
||||
--hide-extension "Tunarr.app" \
|
||||
--app-drop-link 600 185 \
|
||||
--skip-jenkins \
|
||||
--no-internet-enable \
|
||||
"Tunarr.dmg" \
|
||||
"Tunarr.app/"
|
||||
|
||||
- name: Notarize
|
||||
shell: bash
|
||||
run: |
|
||||
xcrun notarytool submit Tunarr.dmg --apple-id "${{ secrets.AC_USERNAME }}" --password "${{ secrets.AC_PASSWORD }}" --team-id XX35C4MZN8 --wait
|
||||
xcrun stapler staple Tunarr.dmg
|
||||
|
||||
- name: Finalize
|
||||
shell: bash
|
||||
run: |
|
||||
mv Tunarr.dmg "${{env.RELEASE_NAME}}.dmg"
|
||||
|
||||
- name: Upload Edge Binary
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: Tunarr Edge
|
||||
tag_name: edge
|
||||
prerelease: true
|
||||
files: |
|
||||
${{ env.RELEASE_NAME }}.dmg
|
||||
if: github.ref == format('refs/heads/{0}', 'dev') && (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
|
||||
|
||||
- name: Upload Binaries
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
${{ env.RELEASE_NAME }}.dmg
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
BIN
design/Tunarr.icns
Normal file
556
macos/Tunarr/Tunarr.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,556 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 77;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
14E9EAAB2E35689400486B60 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 14E9EA942E35689100486B60 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 14E9EA9B2E35689100486B60;
|
||||
remoteInfo = Tunarr;
|
||||
};
|
||||
14E9EAB52E35689400486B60 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 14E9EA942E35689100486B60 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 14E9EA9B2E35689100486B60;
|
||||
remoteInfo = Tunarr;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
14E9EA9C2E35689100486B60 /* Tunarr.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tunarr.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
14E9EAAA2E35689400486B60 /* TunarrTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TunarrTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
14E9EAB42E35689400486B60 /* TunarrUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TunarrUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
14E9EA9E2E35689100486B60 /* Tunarr */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = Tunarr;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14E9EAAD2E35689400486B60 /* TunarrTests */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = TunarrTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14E9EAB72E35689400486B60 /* TunarrUITests */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = TunarrUITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
14E9EA992E35689100486B60 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14E9EAA72E35689400486B60 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14E9EAB12E35689400486B60 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
14E9EA932E35689100486B60 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14E9EA9E2E35689100486B60 /* Tunarr */,
|
||||
14E9EAAD2E35689400486B60 /* TunarrTests */,
|
||||
14E9EAB72E35689400486B60 /* TunarrUITests */,
|
||||
14E9EA9D2E35689100486B60 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14E9EA9D2E35689100486B60 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14E9EA9C2E35689100486B60 /* Tunarr.app */,
|
||||
14E9EAAA2E35689400486B60 /* TunarrTests.xctest */,
|
||||
14E9EAB42E35689400486B60 /* TunarrUITests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
14E9EA9B2E35689100486B60 /* Tunarr */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 14E9EABE2E35689400486B60 /* Build configuration list for PBXNativeTarget "Tunarr" */;
|
||||
buildPhases = (
|
||||
14E9EA982E35689100486B60 /* Sources */,
|
||||
14E9EA992E35689100486B60 /* Frameworks */,
|
||||
14E9EA9A2E35689100486B60 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
14E9EA9E2E35689100486B60 /* Tunarr */,
|
||||
);
|
||||
name = Tunarr;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = Tunarr;
|
||||
productReference = 14E9EA9C2E35689100486B60 /* Tunarr.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
14E9EAA92E35689400486B60 /* TunarrTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 14E9EAC12E35689400486B60 /* Build configuration list for PBXNativeTarget "TunarrTests" */;
|
||||
buildPhases = (
|
||||
14E9EAA62E35689400486B60 /* Sources */,
|
||||
14E9EAA72E35689400486B60 /* Frameworks */,
|
||||
14E9EAA82E35689400486B60 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
14E9EAAC2E35689400486B60 /* PBXTargetDependency */,
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
14E9EAAD2E35689400486B60 /* TunarrTests */,
|
||||
);
|
||||
name = TunarrTests;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = TunarrTests;
|
||||
productReference = 14E9EAAA2E35689400486B60 /* TunarrTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
14E9EAB32E35689400486B60 /* TunarrUITests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 14E9EAC42E35689400486B60 /* Build configuration list for PBXNativeTarget "TunarrUITests" */;
|
||||
buildPhases = (
|
||||
14E9EAB02E35689400486B60 /* Sources */,
|
||||
14E9EAB12E35689400486B60 /* Frameworks */,
|
||||
14E9EAB22E35689400486B60 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
14E9EAB62E35689400486B60 /* PBXTargetDependency */,
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
14E9EAB72E35689400486B60 /* TunarrUITests */,
|
||||
);
|
||||
name = TunarrUITests;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = TunarrUITests;
|
||||
productReference = 14E9EAB42E35689400486B60 /* TunarrUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
14E9EA942E35689100486B60 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1640;
|
||||
LastUpgradeCheck = 1640;
|
||||
TargetAttributes = {
|
||||
14E9EA9B2E35689100486B60 = {
|
||||
CreatedOnToolsVersion = 16.4;
|
||||
};
|
||||
14E9EAA92E35689400486B60 = {
|
||||
CreatedOnToolsVersion = 16.4;
|
||||
TestTargetID = 14E9EA9B2E35689100486B60;
|
||||
};
|
||||
14E9EAB32E35689400486B60 = {
|
||||
CreatedOnToolsVersion = 16.4;
|
||||
TestTargetID = 14E9EA9B2E35689100486B60;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 14E9EA972E35689100486B60 /* Build configuration list for PBXProject "Tunarr" */;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 14E9EA932E35689100486B60;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = 14E9EA9D2E35689100486B60 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
14E9EA9B2E35689100486B60 /* Tunarr */,
|
||||
14E9EAA92E35689400486B60 /* TunarrTests */,
|
||||
14E9EAB32E35689400486B60 /* TunarrUITests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
14E9EA9A2E35689100486B60 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14E9EAA82E35689400486B60 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14E9EAB22E35689400486B60 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
14E9EA982E35689100486B60 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14E9EAA62E35689400486B60 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14E9EAB02E35689400486B60 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
14E9EAAC2E35689400486B60 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 14E9EA9B2E35689100486B60 /* Tunarr */;
|
||||
targetProxy = 14E9EAAB2E35689400486B60 /* PBXContainerItemProxy */;
|
||||
};
|
||||
14E9EAB62E35689400486B60 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 14E9EA9B2E35689100486B60 /* Tunarr */;
|
||||
targetProxy = 14E9EAB52E35689400486B60 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
14E9EABC2E35689400486B60 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
14E9EABD2E35689400486B60 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
14E9EABF2E35689400486B60 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = Tunarr/Tunarr.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cbenincasa.Tunarr;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
14E9EAC02E35689400486B60 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = Tunarr/Tunarr.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cbenincasa.Tunarr;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
14E9EAC22E35689400486B60 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.5;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cbenincasa.TunarrTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tunarr.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Tunarr";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
14E9EAC32E35689400486B60 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.5;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cbenincasa.TunarrTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tunarr.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Tunarr";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
14E9EAC52E35689400486B60 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cbenincasa.TunarrUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_TARGET_NAME = Tunarr;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
14E9EAC62E35689400486B60 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XX35C4MZN8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cbenincasa.TunarrUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_TARGET_NAME = Tunarr;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
14E9EA972E35689100486B60 /* Build configuration list for PBXProject "Tunarr" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
14E9EABC2E35689400486B60 /* Debug */,
|
||||
14E9EABD2E35689400486B60 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
14E9EABE2E35689400486B60 /* Build configuration list for PBXNativeTarget "Tunarr" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
14E9EABF2E35689400486B60 /* Debug */,
|
||||
14E9EAC02E35689400486B60 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
14E9EAC12E35689400486B60 /* Build configuration list for PBXNativeTarget "TunarrTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
14E9EAC22E35689400486B60 /* Debug */,
|
||||
14E9EAC32E35689400486B60 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
14E9EAC42E35689400486B60 /* Build configuration list for PBXNativeTarget "TunarrUITests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
14E9EAC52E35689400486B60 /* Debug */,
|
||||
14E9EAC62E35689400486B60 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 14E9EA942E35689100486B60 /* Project object */;
|
||||
}
|
||||
7
macos/Tunarr/Tunarr.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Tunarr.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
37
macos/Tunarr/Tunarr/AppDelegate.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// Tunarr
|
||||
//
|
||||
// Created by Christian Benincasa on 7/26/25.
|
||||
//
|
||||
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
let bundle = Bundle.main
|
||||
var task = Process()
|
||||
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
guard let executablePath = Bundle.main.url(forAuxiliaryExecutable: "tunarr-macos")
|
||||
else {
|
||||
/// TODO: Do a popup here.
|
||||
NSLog("Error: Bundled executable 'tunarr-macos' not found.")
|
||||
return
|
||||
}
|
||||
|
||||
task.executableURL = executablePath
|
||||
do {
|
||||
try task.run()
|
||||
NSLog("Successfully started Tunarr subprocess.")
|
||||
} catch {
|
||||
NSLog("Could not launch Tunarr. Reason: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
NSLog("Shutting down Tunarr.")
|
||||
task.terminate()
|
||||
task.waitUntilExit()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tunarr_16x16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_16x16@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_32x32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_32x32@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_128x128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_128x128@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_256x256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_256x256@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_512x512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "tunarr_512_512@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 14 KiB |
6
macos/Tunarr/Tunarr/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "7x7"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "7x7"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "11x11"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "11x11"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "24x24"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "24x24"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "100x100"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "100x100"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
23
macos/Tunarr/Tunarr/Assets.xcassets/StatusBarButtonImage.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "favicon.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "favicon 1.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "favicon 2.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
25
macos/Tunarr/Tunarr/Assets.xcassets/StatusBarButtonImage.imageset/favicon 1.svg
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
line { stroke: #231A12; }
|
||||
path.darkMode, circle { fill: #231A12; }
|
||||
circle.button {fill: white}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
line { stroke: #474143 }
|
||||
path.darkMode, circle { fill: #474143 }
|
||||
circle.button {fill: white}
|
||||
}
|
||||
</style>
|
||||
<line class="darkMode" x1="13.0531" y1="3.85848" x2="15.1559" y2="7.61348" stroke="#231A12"/>
|
||||
<line x1="18.3012" y1="3.78277" x2="15.8843" y2="7.34375" stroke="#231A12"/>
|
||||
<path class="darkMode" d="M0 17C0 11.4772 4.47715 7 10 7H22C27.5228 7 32 11.4772 32 17V18C32 23.5228 27.5228 28 22 28H10C4.47715 28 0 23.5228 0 18V17Z" fill="#231A12"/>
|
||||
<path class="darkMode" d="M0 8.48936C0 7.66681 0.69548 7 1.5534 7H30.4466C31.3045 7 32 7.66681 32 8.48936V26.5106C32 27.3332 31.3045 28 30.4466 28H1.5534C0.69548 28 0 27.3332 0 26.5106V8.48936Z" fill="#231A12"/>
|
||||
<circle cx="13" cy="4" r="1" fill="#231A12"/>
|
||||
<circle cx="18" cy="4" r="1" fill="#231A12"/>
|
||||
<path d="M3.00397 11.5614C3.00397 11.0091 3.45168 10.5614 4.00397 10.5614H8.33894V24.53H4.00397C3.45168 24.53 3.00397 24.0823 3.00397 23.53V11.5614Z" fill="#DD3C2C"/>
|
||||
<path d="M18.8472 10.5614H23.1822C23.7345 10.5614 24.1822 11.0091 24.1822 11.5614V23.53C24.1822 24.0823 23.7345 24.53 23.1822 24.53H18.8472V10.5614Z" fill="#E98E1D"/>
|
||||
<rect x="13.6739" y="10.5614" width="5.33497" height="13.9686" fill="#68AAE5"/>
|
||||
<rect x="8.33899" y="10.5614" width="5.33497" height="13.9686" fill="#8DCA23"/>
|
||||
<circle class="button" cx="28" cy="14" r="1" fill="white"/>
|
||||
<circle class="button" cx="28" cy="22" r="1" fill="white"/>
|
||||
<circle class="button" cx="28" cy="18" r="1" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
25
macos/Tunarr/Tunarr/Assets.xcassets/StatusBarButtonImage.imageset/favicon 2.svg
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
line { stroke: #231A12; }
|
||||
path.darkMode, circle { fill: #231A12; }
|
||||
circle.button {fill: white}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
line { stroke: #474143 }
|
||||
path.darkMode, circle { fill: #474143 }
|
||||
circle.button {fill: white}
|
||||
}
|
||||
</style>
|
||||
<line class="darkMode" x1="13.0531" y1="3.85848" x2="15.1559" y2="7.61348" stroke="#231A12"/>
|
||||
<line x1="18.3012" y1="3.78277" x2="15.8843" y2="7.34375" stroke="#231A12"/>
|
||||
<path class="darkMode" d="M0 17C0 11.4772 4.47715 7 10 7H22C27.5228 7 32 11.4772 32 17V18C32 23.5228 27.5228 28 22 28H10C4.47715 28 0 23.5228 0 18V17Z" fill="#231A12"/>
|
||||
<path class="darkMode" d="M0 8.48936C0 7.66681 0.69548 7 1.5534 7H30.4466C31.3045 7 32 7.66681 32 8.48936V26.5106C32 27.3332 31.3045 28 30.4466 28H1.5534C0.69548 28 0 27.3332 0 26.5106V8.48936Z" fill="#231A12"/>
|
||||
<circle cx="13" cy="4" r="1" fill="#231A12"/>
|
||||
<circle cx="18" cy="4" r="1" fill="#231A12"/>
|
||||
<path d="M3.00397 11.5614C3.00397 11.0091 3.45168 10.5614 4.00397 10.5614H8.33894V24.53H4.00397C3.45168 24.53 3.00397 24.0823 3.00397 23.53V11.5614Z" fill="#DD3C2C"/>
|
||||
<path d="M18.8472 10.5614H23.1822C23.7345 10.5614 24.1822 11.0091 24.1822 11.5614V23.53C24.1822 24.0823 23.7345 24.53 23.1822 24.53H18.8472V10.5614Z" fill="#E98E1D"/>
|
||||
<rect x="13.6739" y="10.5614" width="5.33497" height="13.9686" fill="#68AAE5"/>
|
||||
<rect x="8.33899" y="10.5614" width="5.33497" height="13.9686" fill="#8DCA23"/>
|
||||
<circle class="button" cx="28" cy="14" r="1" fill="white"/>
|
||||
<circle class="button" cx="28" cy="22" r="1" fill="white"/>
|
||||
<circle class="button" cx="28" cy="18" r="1" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
25
macos/Tunarr/Tunarr/Assets.xcassets/StatusBarButtonImage.imageset/favicon.svg
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
line { stroke: #231A12; }
|
||||
path.darkMode, circle { fill: #231A12; }
|
||||
circle.button {fill: white}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
line { stroke: #474143 }
|
||||
path.darkMode, circle { fill: #474143 }
|
||||
circle.button {fill: white}
|
||||
}
|
||||
</style>
|
||||
<line class="darkMode" x1="13.0531" y1="3.85848" x2="15.1559" y2="7.61348" stroke="#231A12"/>
|
||||
<line x1="18.3012" y1="3.78277" x2="15.8843" y2="7.34375" stroke="#231A12"/>
|
||||
<path class="darkMode" d="M0 17C0 11.4772 4.47715 7 10 7H22C27.5228 7 32 11.4772 32 17V18C32 23.5228 27.5228 28 22 28H10C4.47715 28 0 23.5228 0 18V17Z" fill="#231A12"/>
|
||||
<path class="darkMode" d="M0 8.48936C0 7.66681 0.69548 7 1.5534 7H30.4466C31.3045 7 32 7.66681 32 8.48936V26.5106C32 27.3332 31.3045 28 30.4466 28H1.5534C0.69548 28 0 27.3332 0 26.5106V8.48936Z" fill="#231A12"/>
|
||||
<circle cx="13" cy="4" r="1" fill="#231A12"/>
|
||||
<circle cx="18" cy="4" r="1" fill="#231A12"/>
|
||||
<path d="M3.00397 11.5614C3.00397 11.0091 3.45168 10.5614 4.00397 10.5614H8.33894V24.53H4.00397C3.45168 24.53 3.00397 24.0823 3.00397 23.53V11.5614Z" fill="#DD3C2C"/>
|
||||
<path d="M18.8472 10.5614H23.1822C23.7345 10.5614 24.1822 11.0091 24.1822 11.5614V23.53C24.1822 24.0823 23.7345 24.53 23.1822 24.53H18.8472V10.5614Z" fill="#E98E1D"/>
|
||||
<rect x="13.6739" y="10.5614" width="5.33497" height="13.9686" fill="#68AAE5"/>
|
||||
<rect x="8.33899" y="10.5614" width="5.33497" height="13.9686" fill="#8DCA23"/>
|
||||
<circle class="button" cx="28" cy="14" r="1" fill="white"/>
|
||||
<circle class="button" cx="28" cy="22" r="1" fill="white"/>
|
||||
<circle class="button" cx="28" cy="18" r="1" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 52 KiB |
8
macos/Tunarr/Tunarr/Info.plist
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
22
macos/Tunarr/Tunarr/Tunarr.entitlements
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.automation.apple-events</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<false/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
47
macos/Tunarr/Tunarr/TunarrApp.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// TunarrApp.swift
|
||||
// Tunarr
|
||||
//
|
||||
// Created by Christian Benincasa on 7/26/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct TunarrApp: App {
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
|
||||
var body: some Scene {
|
||||
MenuBarExtra("Tunarr", image: "StatusBarButtonImage") {
|
||||
Button("Launch Web UI") {
|
||||
let portString = ProcessInfo.processInfo.environment[
|
||||
"TUNARR_SERVER_PORT"
|
||||
]
|
||||
NSLog("Port string is \(portString ?? "null")")
|
||||
let port = Int(portString ?? "") ?? 8000
|
||||
let url = "http://localhost:\(port)"
|
||||
NSWorkspace.shared.open(NSURL(string: url)! as URL)
|
||||
}
|
||||
Button("Show Logs") {
|
||||
NSWorkspace.shared.activateFileViewerSelecting(
|
||||
[
|
||||
URL(
|
||||
fileURLWithPath:
|
||||
FileManager.default
|
||||
.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(
|
||||
"Library"
|
||||
).appendingPathComponent("Preferences")
|
||||
.appendingPathComponent("tunarr")
|
||||
.appendingPathComponent("logs").path
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
Divider()
|
||||
Button("Quit Tunarr") {
|
||||
NSApplication.shared.terminate(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
macos/Tunarr/TunarrTests/TunarrTests.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// TunarrTests.swift
|
||||
// TunarrTests
|
||||
//
|
||||
// Created by Christian Benincasa on 7/26/25.
|
||||
//
|
||||
|
||||
import Testing
|
||||
@testable import Tunarr
|
||||
|
||||
struct TunarrTests {
|
||||
|
||||
@Test func example() async throws {
|
||||
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||
}
|
||||
|
||||
}
|
||||
41
macos/Tunarr/TunarrUITests/TunarrUITests.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// TunarrUITests.swift
|
||||
// TunarrUITests
|
||||
//
|
||||
// Created by Christian Benincasa on 7/26/25.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
final class TunarrUITests: XCTestCase {
|
||||
|
||||
override func setUpWithError() throws {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
|
||||
// In UI tests it is usually best to stop immediately when a failure occurs.
|
||||
continueAfterFailure = false
|
||||
|
||||
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testExample() throws {
|
||||
// UI tests must launch the application that they test.
|
||||
let app = XCUIApplication()
|
||||
app.launch()
|
||||
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testLaunchPerformance() throws {
|
||||
// This measures how long it takes to launch your application.
|
||||
measure(metrics: [XCTApplicationLaunchMetric()]) {
|
||||
XCUIApplication().launch()
|
||||
}
|
||||
}
|
||||
}
|
||||
33
macos/Tunarr/TunarrUITests/TunarrUITestsLaunchTests.swift
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// TunarrUITestsLaunchTests.swift
|
||||
// TunarrUITests
|
||||
//
|
||||
// Created by Christian Benincasa on 7/26/25.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
final class TunarrUITestsLaunchTests: XCTestCase {
|
||||
|
||||
override class var runsForEachTargetApplicationUIConfiguration: Bool {
|
||||
true
|
||||
}
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testLaunch() throws {
|
||||
let app = XCUIApplication()
|
||||
app.launch()
|
||||
|
||||
// Insert steps here to perform after app launch but before taking a screenshot,
|
||||
// such as logging into a test account or navigating somewhere in the app
|
||||
|
||||
let attachment = XCTAttachment(screenshot: app.screenshot())
|
||||
attachment.name = "Launch Screen"
|
||||
attachment.lifetime = .keepAlways
|
||||
add(attachment)
|
||||
}
|
||||
}
|
||||
22
scripts/bundle-macos.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BINARY_NAME="$1"
|
||||
SCRIPT_FOLDER=$(dirname "${BASH_SOURCE[0]}")
|
||||
REPO_ROOT=$(realpath "$SCRIPT_FOLDER/..")
|
||||
APP_NAME="$REPO_ROOT/Tunarr.app"
|
||||
|
||||
if [ -d "$APP_NAME" ]
|
||||
then
|
||||
rm -rf "$APP_NAME"
|
||||
fi
|
||||
|
||||
pushd "$REPO_ROOT/macos/Tunarr" || exit
|
||||
|
||||
xcodebuild build
|
||||
cp -R "$REPO_ROOT/macos/Tunarr/build/Release/Tunarr.app" "$APP_NAME"
|
||||
|
||||
popd || exit
|
||||
|
||||
cp -a "$REPO_ROOT/server/bin/$BINARY_NAME" "$APP_NAME/Contents/MacOS/tunarr-macos"
|
||||
|
||||
chmod +x "$APP_NAME/Contents/MacOS/tunarr-macos"
|
||||
3
scripts/gen-icns.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
iconutil -c icns -o ./design/Tunarr.icns macos/Tunarr/Tunarr/Assets.xcassets/TunarrIcon.iconset
|
||||
11
scripts/sign-macos-dmg.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#! /bin/bash
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_FOLDER=$(dirname "${BASH_SOURCE[0]}")
|
||||
REPO_ROOT=$(realpath "$SCRIPT_FOLDER/..")
|
||||
DMG_NAME="$REPO_ROOT/Tunarr.dmg"
|
||||
ENTITLEMENTS="$REPO_ROOT/macos/Tunarr/Tunarr/Tunarr.entitlements"
|
||||
SIGNING_IDENTITY="040A9C3F4C8D3D983822CCB65959A6FDB9DACDCD"
|
||||
|
||||
codesign --force --timestamp --options=runtime --entitlements "$ENTITLEMENTS" --sign "$SIGNING_IDENTITY" "$DMG_NAME"
|
||||
9
scripts/sign-macos.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_FOLDER=$(dirname "${BASH_SOURCE[0]}")
|
||||
REPO_ROOT=$(realpath "$SCRIPT_FOLDER/..")
|
||||
APP_NAME="$REPO_ROOT/Tunarr.app"
|
||||
ENTITLEMENTS="$REPO_ROOT/macos/Tunarr/Tunarr/Tunarr.entitlements"
|
||||
SIGNING_IDENTITY="040A9C3F4C8D3D983822CCB65959A6FDB9DACDCD"
|
||||
|
||||
codesign --force --verbose --timestamp --options=runtime --entitlements "$ENTITLEMENTS" --sign "$SIGNING_IDENTITY" --deep "$APP_NAME"
|
||||