Skip to content
86 changes: 56 additions & 30 deletions .github/workflows/desktop_cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ jobs:
permissions:
contents: write
runs-on: macos-14
strategy:
fail-fast: false
matrix:
include:
- target: aarch64-apple-darwin
arch: aarch64
artifact_name: silicon
include_am: true
- target: x86_64-apple-darwin
arch: x86_64
artifact_name: intel
include_am: false
defaults:
run:
shell: bash
Expand All @@ -83,19 +95,22 @@ jobs:
with:
platform: macos
- uses: ./.github/actions/pnpm_install
- uses: ./.github/actions/argmax_sdk_setup
- if: ${{ matrix.include_am }}
uses: ./.github/actions/argmax_sdk_setup
with:
api-token: ${{ secrets.AM_SECRET_TOKEN }}
- run: pnpm -F ui build
- run: |
aws s3 cp s3://argmax/stt apps/desktop/src-tauri/binaries/stt-aarch64-apple-darwin \
- if: ${{ matrix.include_am }}
run: |
aws s3 cp s3://argmax/stt apps/desktop/src-tauri/binaries/stt-${{ matrix.target }} \
--endpoint-url ${{ secrets.CLOUDFLARE_R2_ENDPOINT_URL }} \
--region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
- run: |
chmod +x ./apps/desktop/src-tauri/binaries/stt-aarch64-apple-darwin
- if: ${{ matrix.include_am }}
run: |
chmod +x ./apps/desktop/src-tauri/binaries/stt-${{ matrix.target }}
./scripts/sidecar.sh "./apps/desktop/${{ env.TAURI_CONF_PATH }}" "binaries/stt"
- run: ./scripts/resource.sh "./apps/desktop/${{ env.TAURI_CONF_PATH }}" "resources/libonnxruntime.dylib"
- uses: ./.github/actions/apple_cert
Expand All @@ -109,12 +124,11 @@ jobs:
if [[ "${{ inputs.channel }}" == "staging" ]]; then
FEATURES_FLAG="--features devtools"
fi
pnpm -F desktop tauri build --target aarch64-apple-darwin --config ${{ env.TAURI_CONF_PATH }} --verbose $FEATURES_FLAG
pnpm -F desktop tauri build --target ${{ matrix.target }} --config ${{ env.TAURI_CONF_PATH }} --verbose $FEATURES_FLAG
env:
# https://github.com/tauri-apps/tauri-action/issues/740
CI: false
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AM_API_KEY: ${{ secrets.AM_API_KEY }}
AM_API_KEY: ${{ matrix.include_am && secrets.AM_API_KEY || '' }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
APPLE_ID: ${{ secrets.APPLE_ID }}
Expand All @@ -133,7 +147,7 @@ jobs:
VITE_PRO_PRODUCT_ID: ${{ secrets.VITE_PRO_PRODUCT_ID }}
- run: |
mkdir -p target/release/
find target/aarch64-apple-darwin/release -type f -not -path "*/\.*" -exec cp {} target/release/ \;
find target/${{ matrix.target }}/release -type f -not -path "*/\.*" -exec cp {} target/release/ \;
shell: bash
working-directory: ./apps/desktop/src-tauri
- if: ${{ inputs.channel != 'staging' }}
Expand All @@ -147,10 +161,10 @@ jobs:
working-directory: ./apps/desktop
- if: ${{ inputs.channel != 'staging' }}
run: |
DMG_FILE=$(find "apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/" -name "*.dmg" -type f)
cp "$DMG_FILE" "hyprnote-macos-aarch64.dmg"
aws s3 cp "hyprnote-macos-aarch64.dmg" \
"s3://hyprnote-build/desktop/${{ needs.compute-version.outputs.version }}/hyprnote-macos-aarch64.dmg" \
DMG_FILE=$(find "apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/" -name "*.dmg" -type f)
cp "$DMG_FILE" "hyprnote-macos-${{ matrix.arch }}.dmg"
aws s3 cp "hyprnote-macos-${{ matrix.arch }}.dmg" \
"s3://hyprnote-build/desktop/${{ needs.compute-version.outputs.version }}/hyprnote-macos-${{ matrix.arch }}.dmg" \
--endpoint-url ${{ secrets.CLOUDFLARE_R2_ENDPOINT_URL }} \
--region auto
env:
Expand All @@ -159,8 +173,8 @@ jobs:
- if: ${{ inputs.channel == 'staging' }}
uses: actions/upload-artifact@v4
with:
name: hyprnote-staging-macos
path: apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/*.dmg
name: hyprnote-staging-macos-${{ matrix.artifact_name }}
path: apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg
retention-days: 3

build-linux:
Expand Down Expand Up @@ -261,18 +275,22 @@ jobs:
channel: ${{ env.RELEASE_CHANNEL }}
framework: tauri
working-directory: ./apps/desktop
- name: Download macOS DMG from S3
- if: ${{ needs.build-macos.result == 'success' }}
run: |
aws s3 cp \
"s3://hyprnote-build/desktop/${{ needs.compute-version.outputs.version }}/hyprnote-macos-aarch64.dmg" \
"hyprnote-macos-aarch64.dmg" \
--endpoint-url ${{ secrets.CLOUDFLARE_R2_ENDPOINT_URL }} \
--region auto
aws s3 cp \
"s3://hyprnote-build/desktop/${{ needs.compute-version.outputs.version }}/hyprnote-macos-x86_64.dmg" \
"hyprnote-macos-x86_64.dmg" \
--endpoint-url ${{ secrets.CLOUDFLARE_R2_ENDPOINT_URL }} \
--region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
- name: Download Linux AppImage from S3 (if available)
if: ${{ needs.build-linux.result == 'success' }}
- if: ${{ needs.build-linux.result == 'success' }}
run: |
aws s3 cp \
"s3://hyprnote-build/desktop/${{ needs.compute-version.outputs.version }}/hyprnote-linux-x86_64.AppImage" \
Expand All @@ -287,22 +305,30 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
custom_tag: desktop_v${{ needs.compute-version.outputs.version }}
tag_prefix: ""
- name: Create GitHub release with macOS only
if: ${{ needs.build-linux.result != 'success' }}
uses: ncipollo/release-action@v1
with:
tag: desktop_v${{ needs.compute-version.outputs.version }}
name: desktop_v${{ needs.compute-version.outputs.version }}
body: "https://hyprnote.com/changelog/${{ needs.compute-version.outputs.version }}"
artifacts: "hyprnote-macos-aarch64.dmg"
- name: Create GitHub release with macOS + Linux
if: ${{ needs.build-linux.result == 'success' }}
uses: ncipollo/release-action@v1
- id: artifacts
run: |
ARTIFACTS=""
if [[ "${{ needs.build-macos.result }}" == "success" ]]; then
ARTIFACTS="hyprnote-macos-aarch64.dmg,hyprnote-macos-x86_64.dmg"
fi
if [[ "${{ needs.build-linux.result }}" == "success" ]]; then
if [[ -n "$ARTIFACTS" ]]; then
ARTIFACTS="$ARTIFACTS,hyprnote-linux-x86_64.AppImage"
else
ARTIFACTS="hyprnote-linux-x86_64.AppImage"
fi
fi
if [[ -z "$ARTIFACTS" ]]; then
echo "No artifacts to release" >&2
exit 1
fi
echo "list=$ARTIFACTS" >> $GITHUB_OUTPUT
- uses: ncipollo/release-action@v1
with:
tag: desktop_v${{ needs.compute-version.outputs.version }}
name: desktop_v${{ needs.compute-version.outputs.version }}
body: "https://hyprnote.com/changelog/${{ needs.compute-version.outputs.version }}"
artifacts: "hyprnote-macos-aarch64.dmg,hyprnote-linux-x86_64.AppImage"
artifacts: ${{ steps.artifacts.outputs.list }}
- run: |
set -e
curl -f -X POST \
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"@tauri-apps/plugin-fs": "^2.4.4",
"@tauri-apps/plugin-http": "^2.5.4",
"@tauri-apps/plugin-opener": "^2.5.2",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-shell": "^2.3.3",
"@tauri-apps/plugin-store": "^2.4.1",
Expand Down
2 changes: 0 additions & 2 deletions apps/desktop/src/components/main/sidebar/search/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { SearchXIcon } from "lucide-react";

import { cn } from "@hypr/utils";

import {
type GroupedSearchResults,
useSearch,
Expand Down
32 changes: 24 additions & 8 deletions apps/desktop/src/components/settings/ai/stt/select.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useForm } from "@tanstack/react-form";
import { useQueries } from "@tanstack/react-query";
import { useQueries, useQuery } from "@tanstack/react-query";
import { arch } from "@tauri-apps/plugin-os";

import { Input } from "@hypr/ui/components/ui/input";
import {
Expand Down Expand Up @@ -219,6 +220,14 @@ function useConfiguredMapping(): Record<
main.STORE_ID,
);

const targetArch = useQuery({
queryKey: ["target-arch"],
queryFn: () => arch(),
staleTime: Infinity,
});

const isAppleSilicon = targetArch.data === "aarch64";

const [p2, p3, tinyEn, smallEn] = useQueries({
queries: [
sttModelQueries.isDownloaded("am-parakeet-v2"),
Expand All @@ -235,17 +244,24 @@ function useConfiguredMapping(): Record<
}

if (provider.id === "hyprnote") {
const models = [
{ id: "cloud", isDownloaded: billing.isPro },
{ id: "QuantizedTinyEn", isDownloaded: tinyEn.data ?? false },
{ id: "QuantizedSmallEn", isDownloaded: smallEn.data ?? false },
];

if (isAppleSilicon) {
models.push(
{ id: "am-parakeet-v2", isDownloaded: p2.data ?? false },
{ id: "am-parakeet-v3", isDownloaded: p3.data ?? false },
);
}

return [
provider.id,
{
configured: true,
models: [
{ id: "cloud", isDownloaded: billing.isPro },
{ id: "am-parakeet-v2", isDownloaded: p2.data ?? false },
{ id: "am-parakeet-v3", isDownloaded: p3.data ?? false },
{ id: "QuantizedTinyEn", isDownloaded: tinyEn.data ?? false },
{ id: "QuantizedSmallEn", isDownloaded: smallEn.data ?? false },
],
models,
},
];
}
Expand Down
31 changes: 31 additions & 0 deletions apps/web/src/routes/_view/changelog/$slug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,42 @@ function HeroSection({ changelog }: { changelog: ChangelogWithMeta }) {
<h1 className="text-4xl sm:text-5xl font-serif tracking-tight text-stone-600 mb-6">
Version {changelog.version}
</h1>
<DownloadButtons version={changelog.version} />
</div>
</div>
);
}

function DownloadButtons({ version }: { version: string }) {
const baseUrl = `https://github.com/fastrepl/hyprnote/releases/download/desktop_v${version}`;

return (
<div className="flex flex-wrap items-center justify-center gap-3 mt-6">
<a
href={`${baseUrl}/hyprnote-macos-aarch64.dmg`}
className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-stone-900 text-white rounded-full hover:bg-stone-800 transition-colors"
>
<Icon icon="simple-icons:apple" className="text-base" />
<span>Apple Silicon</span>
</a>
<a
href={`${baseUrl}/hyprnote-macos-x86_64.dmg`}
className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-stone-100 text-stone-700 border border-stone-200 rounded-full hover:bg-stone-200 transition-colors"
>
<Icon icon="simple-icons:apple" className="text-base" />
<span>Intel Mac</span>
</a>
<a
href={`${baseUrl}/hyprnote-linux-x86_64.AppImage`}
className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-stone-100 text-stone-700 border border-stone-200 rounded-full hover:bg-stone-200 transition-colors"
>
<Icon icon="simple-icons:linux" className="text-base" />
<span>Linux</span>
</a>
</div>
);
}

function ChangelogContentSection({
changelog,
allChangelogs,
Expand Down
9 changes: 9 additions & 0 deletions apps/web/src/routes/_view/download/apple-intel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createFileRoute, redirect } from "@tanstack/react-router";

export const Route = createFileRoute("/_view/download/apple-intel")({
beforeLoad: async () => {
throw redirect({
href: "https://desktop2.hyprnote.com/download/latest/dmg-x86_64?channel=nightly",
});
},
});
9 changes: 5 additions & 4 deletions apps/web/src/routes/_view/download/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ function Component() {
])}
>
<span>
Mac (Apple Silicon) features on-device speech-to-text. Other
platforms coming soon without on-device processing.
Mac (Apple Silicon) features on-device speech-to-text. Intel Mac
available with cloud-based transcription. Other platforms coming
soon.
</span>
</div>

Expand Down Expand Up @@ -57,8 +58,8 @@ function Component() {
<DownloadCard
iconName="simple-icons:apple"
spec="macOS 14.2+ (Intel)"
downloadUrl="#"
available={false}
downloadUrl="/download/apple-intel"
available={true}
/>
<DownloadCard
iconName="simple-icons:windows"
Expand Down
Loading
Loading