Skip to content

Commit 7cd348f

Browse files
jorbenclaude
andauthored
feat(cloud): ✨ Add cloud API integration with authentication and credits (#48)
* docs: 📝 add Claude Code project instructions Add CLAUDE.md with project guidance for Claude Code including: - Common development commands - Architecture overview (three-process Electron, Clean Architecture) - Key conventions (ESM modules, path aliases, IPC format) - Test configuration details - Links to detailed documentation Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * feat(cloud): ✨ add cloud API integration with Clerk authentication Integrate MarkPDFDown Cloud API for cloud-based PDF conversion, including Clerk authentication system for user management. This feature allows users to convert documents using cloud credits alongside local LLM providers. New features: - CloudService for API communication with token-based auth - CloudContext for managing user state, credits, and cloud operations - AccountCenter component for account management and credit display - Cloud model option in UploadPanel with authentication check - Cloud/local task differentiation in task list view - IPC handlers for cloud:setToken, cloud:convert, cloud:getTasks Changes: - Add @clerk/clerk-react dependency for authentication - Add Account tab as default in Settings page - Replace GitHub icon with user profile avatar in sidebar - Update tests to mock CloudContext BREAKING CHANGE: Settings page now defaults to Account tab instead of Model Service Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * feat(i18n): ✨ add internationalization for cloud features Add i18n support for cloud-related UI components across all 6 languages: - AccountCenter: translate account management, credit balance, and history - UploadPanel: translate cloud provider and model names, status messages - Layout: translate user profile tooltip - List: translate cloud/local task type labels - Settings: translate account tab label Add new account.json namespace with translations for: - Account center title and sign in/out buttons - Credit balance section (monthly free, paid credits) - Credit history table columns and type labels Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * feat(i18n): ✨ update credit description texts for account center - Change paid credits description to "$1 USD = 1,500 credits" - Change free credits description to monthly quota with UTC+0 reset time - Rename "Monthly Free Credits" to "Free Credits" across all locales - Remove unused reset_hint and never_expire fields - Align description layout between free and paid credit cards Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * refactor(ui): ♻️ remove local task type icon from task list Remove HomeOutlined icon for local tasks, keeping only cloud icon indicator. Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * fix(types): 🐛 resolve TypeScript type errors in cloud integration - Remove unused imports in CloudService (net, fs, path, FormData) - Add missing getCreditHistory method to CloudService - Remove unused imports in Layout (Space, GithubOutlined) - Remove unused openExternalLink function in Layout - Add cloud API types to WindowAPI and ElectronAPI interfaces - Add window, platform, and app types to electron.d.ts - Add hasRunningTasks type to task API interface - Create CloudFileInput interface for flexible file type handling - Fix UploadPanel to properly convert UploadFile to CloudFileInput Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * feat(auth): ✨ add custom protocol handler for OAuth callback Implement deep linking support for OAuth authentication flow: - Register markpdfdown:// custom protocol for all platforms - Handle OAuth callback URLs in main process - Add IPC bridge to forward auth events to renderer - Replace Clerk modal with inline SignIn component - Configure ClerkProvider with allowedRedirectProtocols - Add onOAuthCallback mock to test setup Co-Authored-By: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com> * feat(auth): ✨ replace Clerk SDK with device flow authentication Remove @clerk/clerk-react dependency and implement a custom device flow (RFC 8628) authentication system via AuthManager. The new flow: - Main process manages tokens (access + refresh) with encrypted storage - Renderer receives auth state changes via IPC event bridge - AccountCenter UI shows user code for browser-based authorization - CloudService retrieves tokens from AuthManager instead of receiving them from the renderer Also updates IPC channels, preload bridge, type definitions, i18n strings, and test mocks to align with the new auth architecture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(auth): 🐛 unwrap API response in fetchUserProfile The fetchUserProfile method was assigning the raw API response directly to userProfile instead of extracting the nested data field. Since the API returns { success, data: CloudUserProfile }, the user's name, email, and avatar_url were all undefined in the renderer, causing avatar and username not to display after login. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(auth): ✨ 添加自定义 User-Agent 和自动 token 刷新功能 在 AuthManager 中添加以下改进: - 添加 buildUserAgent() 函数,为所有 API 请求设置自定义 User-Agent 头 - 添加 fetchWithAuth() 方法,自动携带认证令牌并在 401 时自动刷新 token - 所有 API 请求现在都包含 User-Agent 和正确的认证头 - 改进登出流程,使用 fetchWithAuth 处理认证失败情况 此变更提高了 API 调用的可追踪性和认证流程的健壮性。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ integrate credits API with real backend Replace mock credit data with actual API calls: - Add getCredits() endpoint to fetch current balance - Add type filter support for credit history - Update UI to show monthly and daily credit balances - Add 7 credit transaction types (consume, topup, refund, etc.) - Add TypeScript types for CreditsApiResponse 🤖 Generated with [Claude Code](https://claude.com/claude-code) * feat(cloud): ✨ add multi-tier cloud model selection Add three cloud model tiers with different credit pricing: - Fit Lite: ~10 credits/page - Fit Pro: ~20 credits/page - Fit Ultra: ~60 credits/page Changes: - Update model selector to display 3 options with i18n support - Pass selected model tier through IPC to cloud conversion - Add translations for all 6 supported languages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ add credit usage hint to Account page Add i18n text explaining credit consumption rates for different cloud models (Lite/Pro/Ultra) displayed next to Credit Balance title. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ implement POST /api/v1/convert API integration Replace mock implementation with real API call to create cloud conversion tasks: - Add CreateTaskResponse and CloudModelTier types - Use FormData for multipart/form-data file upload - Support both file path and content as input - Handle API errors properly with structured response - Default to 'lite' model tier if not specified Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ implement full task management API integration Replace mock data with real cloud API calls for complete task lifecycle management. This covers all 10 API endpoints from the client integration guide: Backend integration: - Replace mock getTasks with GET /api/v1/tasks - Add getTaskById, getTaskPages, cancelTask, retryTask, retryPage, getTaskResult, downloadPdf methods to CloudService - Create CloudSSEManager for real-time task event streaming with auto-reconnect, exponential backoff, and heartbeat IPC & Preload: - Add 13 CLOUD IPC channels and CLOUD_TASK_EVENT event - Register 9 new IPC handlers in cloud.handler.ts - Expose all new methods and onCloudTaskEvent in preload bridge Renderer: - Extend CloudContext with 7 new actions and SSE lifecycle - Create cloudTaskMapper utility for API response mapping - Update List page with cloud task actions and SSE live updates - Create CloudPreview page for viewing cloud task results - Add cloud-preview i18n translations for all 6 locales Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ display page images in cloud task detail Add page image support to CloudPreview component by: - Add image_url field to CloudTaskPageResponse type - Add getPageImage IPC channel and handler for proxying image requests - Implement dual URL handling: - Presigned URLs (https://) - use directly in <img> tag - Relative API paths - proxy through main process with auth token - Update CloudPreview left panel to display page images - Handle image loading states and errors gracefully This enables users to view the original PDF page images alongside their markdown conversion results in cloud task details. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(auth): ⚡️ speed up token acquisition after OAuth callback Add checkDeviceTokenStatus() method to immediately verify token status when receiving protocol URL callback, instead of waiting for next polling interval. This reduces token acquisition latency from ~5s to milliseconds. The implementation: - Calls /api/v1/auth/device/token immediately on callback - Stops polling after successful token acquisition - Handles 428 (authorization_pending) gracefully by continuing polling - Thread-safe: concurrent requests don't cause issues Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ display model tier in task list Add model_tier field to CloudTaskResponse type and use it for displaying the correct model tier (lite/pro/ultra) in the task list. Previously the code incorrectly used status_name for model tier mapping. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): align model tier display with upload panel Change task list model name from "Cloud Lite/Pro/Ultra" to "Fit Lite/Pro/Ultra" to match the upload panel selector. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ implement cloud task deletion with terminal state guard Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🐛 refresh credit balance when entering account page Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ui): 🐛 fix account page content overflow by enabling tab-level scrolling - Add height: 100vh and minHeight: 0 to Layout content area so flex children get a constrained height - Make Settings Tabs a flex column filling its container, with only the tab content holder scrolling (tab bar stays fixed) - Add scrollbar styles for settings-tabs consistent with existing model-service-tabs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ add page_range support to cloud convert API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🐛 prevent duplicate SSE connections causing repeated events The cloud task list received each SSE event 3 times because multiple SSE connections were being established concurrently: 1. Main process auto-connect in initializeBackgroundServices 2. Renderer CloudContext useEffect calling sseConnect on auth 3. React re-renders causing disconnect+reconnect race conditions Key changes: - Remove main process SSE auto-connect; let renderer CloudContext manage SSE lifecycle exclusively via IPC to avoid dual entry points - Set connected flag synchronously before any await in connect() to prevent concurrent calls from passing the guard - Abort any lingering stream in startStream() before creating new one - Use authManager.fetchWithAuth for automatic token refresh on 401 - Filter connected/heartbeat control events from renderer forwarding - Fix page_completed counting to use page number (idempotent) instead of naive increment that double-counts on SSE reconnect replay - Fix pdf_ready status mapping from SPLITTING(2) to PROCESSING(3) - Move fetchTasks out of setState callback using queueMicrotask - Add connected event type to CloudSSEEventType for type safety - Reset lastEventId on disconnect to prevent cross-session replays - Add diagnostic logging throughout SSE pipeline Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): ✨ update credit transaction types for pre-auth billing model - Replace consume_settle/page_retry with pre_auth, settle, pre_auth_release - Add frozen fields to CreditsApiResponse for bonus and paid credits - Fix description column to show API description instead of file_name - Reorder credits column before description in history table - Style pre_auth/pre_auth_release amounts as secondary (grey) - Update transaction type translations for all 6 locales Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🐛 fix SSE event loss on reconnection by preserving Last-Event-ID - disconnect() no longer resets lastEventId, preserving resumption point - Add resetAndDisconnect() for explicit logout (clears lastEventId) - Fix duplicate reconnect by clearing pending reconnectTimer - Skip redundant reconnect when stream is aborted (not naturally ended) - Log Last-Event-ID in reconnect/connect for debugging Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(auth): 🐛 distinguish transient vs permanent token refresh failures - Add AuthTokenInvalidError for definitive auth failures (401/403) - Only clear refresh token on permanent failures, keep it for transient errors - Add retry logic for auto-refresh with exponential backoff - Schedule init retry on transient failure during session restore - Fix getAccessToken to attempt refresh when access token is missing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * perf(cloud): ⚡️ reduce task list polling frequency to lower server load Active tasks: 10s → 60s, idle: 30s → 120s. Real-time updates are handled by SSE, polling serves only as a fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cloud): ♻️ align cloud preview actions with local task behavior - Remove Download PDF entry from More Actions menu - Add retry failed pages action (status=8 with failed pages) - Add delete action for terminal-state tasks - Use Dropdown.Button pattern matching local Preview - Add i18n keys for all 6 locales Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(list): 🐛 fix pagination and sorting for combined local/cloud task list - Fetch up to 100 items from each source, then paginate locally - Add unified sortTimestamp field to CloudTask for cross-source sorting - Sort combined list by timestamp (newest first) before pagination - Fix pagination total to include both local and cloud task counts * feat(cloud): ⏱️ add 8-second timeout to cloud API requests Add timeout support to AuthManager.fetchWithAuth() using AbortController. Both initial requests and 401 retry requests now have 8-second timeout. SSE heartbeat timeout (90s) remains unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cloud): 🏷️ add provider name to cloud task model display Append provider name 'Markdown.Fit' to cloud task model_name field for clearer identification of cloud tasks in the task list. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(upload): ✨ add Office file support for cloud conversion Add support for selecting and uploading Office documents (doc, docx, xls, xlsx, ppt, pptx) when using cloud conversion with authenticated users. - Add allowOffice parameter to file select dialog - Add file type detection (pdf, image, office, unsupported) - Show appropriate hints when Office files are not supported - Add validation to prevent unsupported file types Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): ⏱️ adjust timeout based on request type - FormData uploads: 120s timeout - Download requests (/result, /download): no timeout - Other API requests: 8s timeout Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(renderer): ✅ align list and preview tests with latest UI behavior * chore(account): 🚧 disable recharge button until feature is ready Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): 🐛 improve LLM PR review reliability for large diffs - Reduce max diff size from 128KB to 64KB to avoid exceeding LLM context limits - Replace silent curl failure with explicit HTTP status code checking and error output - Add timeout (120s for LLM API, 30s for GitHub API) to prevent hanging requests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): 🐛 fix broken pipe error in diff truncation Replace printf|head pipe with bash substring expansion to avoid SIGPIPE under set -o pipefail when diff exceeds max size. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): 🔧 restore max diff size to 128KB Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): 🐛 fix jq argument list too long for large diffs Use --rawfile to pass system prompt and diff content via temp files instead of --arg CLI arguments, avoiding ARG_MAX limit on Linux. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): 🐛 fix curl argument list too long for LLM request Write request body to temp file and use curl -d @file syntax to avoid ARG_MAX limit when sending large diffs to LLM API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🔒 address PR review security and quality issues - Prevent refresh token plaintext persistence when encryption unavailable - Strict-validate protocol URL paths (only allow auth/callback) - Add missing page_range field to cloud.convert type definition - Gate SSE verbose logging behind isDev check for production perf - URL-encode all path parameters in CloudService API calls Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🔒 address second round PR review issues - Add 100MB file size limit validation in cloud:convert IPC handler - Normalize protocol URL path (lowercase, deduplicate slashes, decode) - Deduplicate concurrent refresh token calls with in-flight promise - Await shell.openExternal and handle browser launch failures - Normalize CRLF to LF in SSE stream parser for server compatibility - Sanitize Content-Disposition filename with path.basename and char filter Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🔒 address third round PR review issues - Use async fs.readFile instead of sync readFileSync for upload (unblock main) - Use async fs.promises.stat in cloud handler for file size validation - Safe decodeURIComponent in protocol URL handler (catch malformed encoding) - Replace brittle URL-substring timeout detection with explicit timeoutMs option - Add content-type validation for SSE stream (reject non text/event-stream) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🐛 fix SSE abort signal and normalize timeout errors - Compose caller signal with timeout signal in fetchWithAuth using AbortSignal.any - SSE disconnect/reconnect now reliably aborts in-flight fetch requests - Normalize timeout AbortError to 'Request timeout' for better UX - Remove duplicate comment line in UploadPanel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cloud): 🔒 harden protocol URL validation and signal compatibility - Validate protocol URL host structurally without decodeURIComponent - Reject percent-encoded characters in host to prevent bypass - Add AbortSignal.any fallback for older runtimes - Reset SSE connected flag on startStream failure to prevent deadlock Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude (anthropic/claude-opus-4.5) <noreply@anthropic.com>
1 parent 10e3a9d commit 7cd348f

79 files changed

Lines changed: 6221 additions & 262 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/llm-pr-review.yml

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ jobs:
6464
}
6565
6666
max_diff_chars=131072
67-
pr_diff_trimmed=$(printf "%s" "$pr_diff" | head -c $max_diff_chars | sed '$d')
67+
pr_diff_trimmed="${pr_diff:0:$max_diff_chars}"
68+
# Trim to last complete line to avoid cutting mid-line
69+
pr_diff_trimmed="${pr_diff_trimmed%$'\n'*}"
6870
6971
system_prompt=$(cat <<'SYSPROMPT'
7072
You are a senior software engineer reviewing a pull request for an Electron desktop application (React 18 + TypeScript + Vite + Prisma/SQLite + Ant Design). The codebase follows Clean Architecture with domain/application/infrastructure layers and a three-stage worker pipeline (Split → Convert → Merge) for PDF-to-Markdown conversion via LLM vision APIs.
@@ -118,12 +120,16 @@ jobs:
118120
SYSPROMPT
119121
)
120122
123+
# Write large variables to temp files to avoid ARG_MAX limit
124+
printf "%s" "$system_prompt" > /tmp/system_prompt.txt
125+
printf "%s" "$pr_diff_trimmed" > /tmp/pr_diff.txt
126+
121127
request_body=$(jq -n \
122128
--arg model "$MODEL_ID" \
123-
--arg system "$system_prompt" \
129+
--rawfile system /tmp/system_prompt.txt \
124130
--arg title "$pr_title" \
125131
--arg body "$pr_body" \
126-
--arg diff "$pr_diff_trimmed" \
132+
--rawfile diff /tmp/pr_diff.txt \
127133
'{
128134
model: $model,
129135
max_tokens: 8192,
@@ -133,16 +139,27 @@ jobs:
133139
]
134140
}')
135141
136-
llm_response=$(curl -sf \
142+
printf "%s" "$request_body" > /tmp/llm_request.json
143+
144+
http_code=$(curl -s -o /tmp/llm_response.json -w "%{http_code}" \
145+
--max-time 120 \
137146
-H "x-api-key: $API_KEY" \
138147
-H "Content-Type: application/json" \
139148
-H "anthropic-version: 2023-06-01" \
140149
"$API_BASE/v1/messages" \
141-
-d "$request_body") || {
142-
echo "::error::LLM API request failed"
150+
-d @/tmp/llm_request.json) || {
151+
echo "::error::LLM API request failed (curl error)"
143152
exit 1
144153
}
145154
155+
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
156+
echo "::error::LLM API returned HTTP $http_code"
157+
cat /tmp/llm_response.json
158+
exit 1
159+
fi
160+
161+
llm_response=$(cat /tmp/llm_response.json)
162+
146163
review_text=$(printf "%s" "$llm_response" | jq -r '[.content[] | select(.type == "text")] | first? | .text // ""')
147164
148165
if [ -z "$review_text" ]; then
@@ -153,7 +170,7 @@ jobs:
153170
154171
review_payload=$(jq -n --arg body "$review_text" '{body: $body, event: "COMMENT"}')
155172
156-
curl -sf \
173+
curl -sf --max-time 30 \
157174
-H "Authorization: Bearer $GITHUB_TOKEN" \
158175
-H "Accept: application/vnd.github+json" \
159176
"https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/reviews" \

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ settings.local.json
4040
# Publish backup
4141
package.json.backup
4242
.npmrc.backup
43+
44+
client-integration-guide.md

CLAUDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,7 @@ Test helpers in `tests/`:
106106
## Database
107107

108108
SQLite via Prisma with 4 models: Provider, Model, Task, TaskDetail. Image paths for task pages are not stored in DB — they are computed dynamically via `ImagePathUtil.getPath(task, page)` as `{tempDir}/{taskId}/page-{page}.png`.
109+
110+
## Communication
111+
112+
Always address the user as "Jorben" when responding.

electron.vite.config.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
1-
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
2-
import react from '@vitejs/plugin-react'
3-
import { resolve } from 'path'
1+
import { defineConfig, externalizeDepsPlugin } from "electron-vite";
2+
import react from "@vitejs/plugin-react";
3+
import { resolve } from "path";
44

55
export default defineConfig({
66
main: {
77
plugins: [externalizeDepsPlugin()],
88
build: {
9-
outDir: 'dist/main'
10-
}
9+
outDir: "dist/main",
10+
},
1111
},
1212
preload: {
1313
plugins: [externalizeDepsPlugin()],
1414
build: {
15-
outDir: 'dist/preload',
15+
outDir: "dist/preload",
1616
rollupOptions: {
1717
output: {
18-
format: 'cjs',
19-
entryFileNames: '[name].js'
20-
}
21-
}
22-
}
18+
format: "cjs",
19+
entryFileNames: "[name].js",
20+
},
21+
},
22+
},
2323
},
2424
renderer: {
2525
plugins: [react()],
2626
resolve: {
2727
alias: {
28-
'@': resolve(__dirname, 'src/renderer')
29-
}
28+
"@": resolve(__dirname, "src/renderer"),
29+
},
3030
},
3131
server: {
32-
port: 5173
32+
port: 15173,
3333
},
3434
build: {
35-
outDir: 'dist/renderer',
35+
outDir: "dist/renderer",
3636
rollupOptions: {
3737
input: {
38-
index: resolve(__dirname, 'src/renderer/index.html')
39-
}
38+
index: resolve(__dirname, "src/renderer/index.html"),
39+
},
4040
},
4141
emptyOutDir: true,
42-
assetsDir: 'assets'
43-
}
44-
}
45-
})
42+
assetsDir: "assets",
43+
},
44+
},
45+
});

package.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@
8585
],
8686
"artifactName": "${productName}-${version}-${arch}.${ext}",
8787
"icon": "public/icons/mac/icon.icns",
88+
"extendInfo": {
89+
"CFBundleURLTypes": [
90+
{
91+
"CFBundleURLSchemes": [
92+
"markpdfdown"
93+
],
94+
"CFBundleURLName": "com.markpdfdown.desktop"
95+
}
96+
]
97+
},
8898
"hardenedRuntime": true,
8999
"gatekeeperAssess": false,
90100
"entitlements": "build/entitlements.mac.plist",
@@ -96,6 +106,12 @@
96106
"target": "nsis",
97107
"artifactName": "${productName}-${version}-${arch}.${ext}",
98108
"icon": "public/icons/win/icon.ico",
109+
"protocols": {
110+
"name": "MarkPDFdown URL",
111+
"schemes": [
112+
"markpdfdown"
113+
]
114+
},
99115
"verifyUpdateCodeSignature": false
100116
},
101117
"nsis": {
@@ -109,7 +125,10 @@
109125
"linux": {
110126
"target": "AppImage",
111127
"artifactName": "${productName}-${version}-${arch}.${ext}",
112-
"icon": "public/icons/png"
128+
"icon": "public/icons/png",
129+
"mimeTypes": [
130+
"x-scheme-handler/markpdfdown"
131+
]
113132
},
114133
"electronDownload": {
115134
"mirror": "https://github.com/electron/electron/releases/download/"

src/core/infrastructure/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const API_BASE_URL = process.env.API_BASE_URL || 'https://markdown.fit';

0 commit comments

Comments
 (0)