Skip to content

Mobile App Custom Proxy#864

Merged
CodeWithCJ merged 8 commits intoCodeWithCJ:mainfrom
apedley:app-custom-proxy
Mar 7, 2026
Merged

Mobile App Custom Proxy#864
CodeWithCJ merged 8 commits intoCodeWithCJ:mainfrom
apedley:app-custom-proxy

Conversation

@apedley
Copy link
Contributor

@apedley apedley commented Mar 7, 2026

Tip

Help us review and merge your PR faster!
Please ensure you have completed the Checklist below.
For Frontend changes, please run pnpm run validate to check for any errors.
PRs that include tests and clear screenshots are highly preferred!

Description

Right now users that run Sparky Fitness behind a reverse proxy tunnel such as Cloudflare or Pangolin have to expose all of the /api/* routes, bypassing the added security of these services. This PR adds support for adding custom proxy headers to the requests sent by the app. This is similar to the solution that Immich uses.

I've also added some documentation for the mobile app - App Store, Testflight, google play group links just like the wiki. Plus a section on how to export diagnostic data and how to set up the app to work with custom proxy headers.

Related Issue

PR type [X] Issue [ ] New Feature [ ] Documentation
Linked Issue: #850

Checklist

Please check all that apply:

  • [MANDATORY for new feature] Alignment: I have raised a GitHub issue and it was reviewed/approved by maintainers
  • Tests: I have included automated tests for my changes.
  • [MANDATORY for UI changes] Screenshots: I have attached "Before" vs "After" screenshots below.
  • [MANDATORY for Frontend changes] Quality: I have run pnpm run validate (especially for Frontend).
  • Translations: I have only updated the English (en) translation file (if applicable).
  • Architecture: My code follows the existing architecture standards.
  • Database Security: I have updated rls_policies.sql for any new user-specific tables.
  • [MANDATORY - ALL] Integrity & License: I certify this is my own work, free of malicious code(phishing, malware, etc.) and I agree to the License terms.

Screenshots (if applicable)

Before

[Insert screenshot/GIF here]

After

[Insert screenshot/GIF here]

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Sparky Fitness mobile app's connectivity and user experience by introducing support for custom proxy headers, which is crucial for users operating behind secure reverse proxies. Alongside this, the mobile app's documentation has been thoroughly updated to guide users through installation, proxy configuration, and troubleshooting. The changes also refine background synchronization permissions on Android for a more robust health data syncing process.

Highlights

  • Custom Proxy Header Support: Implemented the ability for the mobile app to send custom proxy headers with API requests, enabling users behind reverse proxies like Cloudflare or Pangolin to secure their API routes.
  • Enhanced Mobile App Documentation: Added comprehensive documentation for the mobile app, including details on iOS (App Store, Testflight) and Android (APK, Google Play Beta) availability, proxy tunnel setup, and troubleshooting with diagnostic reports.
  • Background Sync Permission Handling: Introduced a mechanism to request and check for background access permissions on Android devices when enabling background synchronization, ensuring proper functionality.
Changelog
  • SparkyFitnessMobile/.prettierignore
    • Added new directories and files to be ignored by Prettier.
  • SparkyFitnessMobile/App.tsx
    • Introduced a new state variable for API key proxy headers.
    • Updated the onUseApiKey callback to include proxy headers.
    • Passed proxy header states to the ServerConfigModal component.
    • Included proxy headers when saving new API key configurations.
  • SparkyFitnessMobile/tests/components/LoginModal.test.tsx
    • Mocked new proxy header related functions in authService and storage.
    • Adjusted existing test assertions to account for proxy headers in onUseApiKey calls.
    • Added a new test case to ensure stale local proxy headers are not reused for saved configurations.
  • SparkyFitnessMobile/tests/services/apiClient.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/exerciseApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/externalFoodSearchApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/foodEntriesApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/foodsApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/goalsApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/healthDataApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/measurementsApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/preferencesApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/profileApi.test.ts
    • Mocked proxyHeadersToRecord from storage service.
  • SparkyFitnessMobile/tests/services/storage.test.ts
    • Updated the default value and test expectations for loadBackgroundSyncEnabled from true to false.
  • SparkyFitnessMobile/app.json
    • Added autolinkingModuleResolution: true to the experiments configuration.
  • SparkyFitnessMobile/package.json
    • Updated react-native and react-native-pager-view dependency versions.
    • Removed pnpm.overrides for side-channel.
    • Added jest-environment-jsdom as a development dependency.
  • SparkyFitnessMobile/pnpm-workspace.yaml
    • Removed the file, as its content was moved to the root package.json.
  • SparkyFitnessMobile/src/components/DevTools.tsx
    • Imported getGrantedPermissions for Health Connect.
    • Added a new function handleCheckBackgroundPermissions to verify background access.
    • Integrated a 'Check BG Permission' button into the Dev Tools UI.
  • SparkyFitnessMobile/src/components/LoginModal.tsx
    • Imported ProxyHeadersModal and ProxyHeader type.
    • Integrated new functions setPendingProxyHeaders and clearPendingProxyHeaders from authService.
    • Updated component props and state to manage proxy headers during login and server configuration.
    • Added a 'Proxy Headers' option to the credentials form for new server entries, utilizing ProxyHeadersModal.
  • SparkyFitnessMobile/src/components/ProxyHeadersModal.tsx
    • Added a new component ProxyHeadersModal to allow users to add, edit, and remove custom proxy headers.
    • Implemented validation within the modal to warn against using reserved header names.
  • SparkyFitnessMobile/src/components/ServerConfig.tsx
    • Updated component props to include proxyHeaders and setProxyHeaders for server configuration.
    • Passed proxy header related props to the ServerConfigModal.
  • SparkyFitnessMobile/src/components/ServerConfigModal.tsx
    • Imported ProxyHeadersModal and ProxyHeader type.
    • Updated component props and state to manage proxy headers for individual server configurations.
    • Added a 'Proxy Headers' button to the server configuration modal, integrating ProxyHeadersModal.
  • SparkyFitnessMobile/src/screens/SettingsScreen.tsx
    • Imported ProxyHeader type and added proxyHeaders state.
    • Changed the initial state of isBackgroundSyncEnabled to false.
    • Included proxyHeaders when saving server configurations.
    • Modified handleEditConfig and handleAddNewConfig to correctly set and clear proxyHeaders state.
    • Passed proxy header states to the ServerConfig component.
    • Added logic to request BackgroundAccessPermission on Android when enabling background sync.
  • SparkyFitnessMobile/src/services/api/apiClient.ts
    • Imported proxyHeadersToRecord from storage service.
    • Applied custom proxy headers to outgoing API requests.
  • SparkyFitnessMobile/src/services/api/authService.ts
    • Introduced pendingProxyHeaders state and utility functions (setPendingProxyHeaders, clearPendingProxyHeaders).
    • Included pendingProxyHeaders in the headers for authentication-related API calls.
  • SparkyFitnessMobile/src/services/api/healthDataApi.ts
    • Imported proxyHeadersToRecord from storage service.
    • Applied custom proxy headers to health data synchronization and server connection check requests.
  • SparkyFitnessMobile/src/services/storage.ts
    • Defined the ProxyHeader interface and added proxyHeaders to the ServerConfig interface.
    • Added proxyHeadersSecureStoreKey and proxyHeadersToRecord utility function.
    • Updated saveServerConfig to store and delete proxy headers in SecureStore.
    • Modified getAllServerConfigs to retrieve proxy headers from SecureStore.
    • Updated deleteServerConfig to remove proxy headers from SecureStore.
    • Changed the default return value for loadBackgroundSyncEnabled to false.
  • SparkyFitnessMobile/tsconfig.json
    • Added a path alias for @workspace/shared.
  • docs/content/2.features/8.mobile-app.md
    • Removed the outdated mobile app documentation file.
  • docs/content/4.developer/1.getting-started.md
    • Renamed the file to docs/content/8.developer/1.getting-started.md.
  • docs/content/4.developer/10.mcp/0.dev.md
    • Renamed the file to docs/content/8.developer/10.mcp/0.dev.md.
  • docs/content/4.developer/10.mcp/1.food.md
    • Renamed the file to docs/content/8.developer/10.mcp/1.food.md.
  • docs/content/4.developer/10.mcp/2.exercise.md
    • Renamed the file to docs/content/8.developer/10.mcp/2.exercise.md.
  • docs/content/4.developer/10.mcp/3.checkin.md
    • Renamed the file to docs/content/8.developer/10.mcp/3.checkin.md.
  • docs/content/4.developer/10.mcp/4.coach.md
    • Renamed the file to docs/content/8.developer/10.mcp/4.coach.md.
  • docs/content/4.developer/10.mcp/5.engagement.md
    • Renamed the file to docs/content/8.developer/10.mcp/5.engagement.md.
  • docs/content/4.developer/10.mcp/6.vision.md
    • Renamed the file to docs/content/8.developer/10.mcp/6.vision.md.
  • docs/content/4.developer/2.architecture.md
    • Renamed the file to docs/content/8.developer/2.architecture.md.
  • docs/content/4.developer/3.contributing.md
    • Renamed the file to docs/content/8.developer/3.contributing.md.
  • docs/content/4.developer/4.database.md
    • Renamed the file to docs/content/8.developer/4.database.md.
  • docs/content/4.developer/5.api-reference.md
    • Renamed the file to docs/content/8.developer/5.api-reference.md.
  • docs/content/4.developer/6.troubleshooting.md
    • Renamed the file to docs/content/8.developer/6.troubleshooting.md.
  • docs/content/4.developer/7.testing.md
    • Renamed the file to docs/content/8.developer/7.testing.md.
  • docs/content/4.developer/8.advanced/1.ai-command-patterns.md
    • Renamed the file to docs/content/8.developer/8.advanced/1.ai-command-patterns.md.
  • docs/content/4.developer/8.advanced/2.chatbot-workflow.md
    • Renamed the file to docs/content/8.developer/8.advanced/2.chatbot-workflow.md.
  • docs/content/4.developer/8.advanced/3.rate-limiting.md
    • Renamed the file to docs/content/8.developer/8.advanced/3.rate-limiting.md.
  • docs/content/4.developer/8.advanced/4.translations.md
    • Renamed the file to docs/content/8.developer/8.advanced/4.translations.md.
  • docs/content/4.developer/8.advanced/5.wger-integration-plan.md
    • Renamed the file to docs/content/8.developer/8.advanced/5.wger-integration-plan.md.
  • docs/content/4.developer/9.translations.md
    • Renamed the file to docs/content/8.developer/9.translations.md.
  • docs/content/4.mobile-app/1.mobile-app.md
    • Added new, comprehensive documentation for the mobile app, covering iOS and Android installation and beta programs.
  • docs/content/4.mobile-app/2.proxy-setup.md
    • Added new documentation detailing how to set up proxy tunnels, with a specific example for Pangolin.
  • docs/content/4.mobile-app/3.troubleshooting.md
    • Added new documentation for troubleshooting, including instructions on generating a diagnostic report.
  • package.json
    • Added pnpm configuration for overrides and onlyBuiltDependencies.
  • pnpm-workspace.yaml
    • Added SparkyFitnessMobile to the list of workspace packages.
    • Added onlyBuiltDependencies configuration.
Activity
  • The author indicated that automated tests for the changes have been included.
  • The author confirmed that only the English translation file was updated, where applicable.
  • The author verified that the code adheres to existing architecture standards.
  • The author certified the integrity and license compliance of the work.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for custom proxy headers in the mobile app, a valuable feature for users behind reverse proxies. The implementation is thorough, covering configuration storage, UI for managing headers, and integration into API requests. The related documentation updates are also clear and helpful.

All identified areas for minor refactoring to improve code maintainability by reducing duplication and enhancing error logging remain valid. My suggestions focus on these aspects. Overall, this is a solid contribution.

const proxyHeadersJson = await SecureStore.getItemAsync(proxyHeadersSecureStoreKey(entry.id), secureStoreOptions);
let proxyHeaders: ProxyHeader[] | undefined;
if (proxyHeadersJson) {
try { proxyHeaders = JSON.parse(proxyHeadersJson); } catch { /* ignore */ }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Silently ignoring a JSON parsing error can make debugging difficult if proxy headers are unexpectedly missing. Consider adding a log here to record the error, which would be helpful for troubleshooting issues with corrupted data in SecureStore.

Suggested change
try { proxyHeaders = JSON.parse(proxyHeadersJson); } catch { /* ignore */ }
try { proxyHeaders = JSON.parse(proxyHeadersJson); } catch (e) { console.error(`Failed to parse proxy headers for config ${entry.id}:`, e); }

Copy link
Contributor Author

@apedley apedley Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got one right! fixed

@CodeWithCJ CodeWithCJ merged commit 6e0cd46 into CodeWithCJ:main Mar 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants