Skip to content

feat: Multi-platform link support (App Store / Google Play) + layout fixes#6

Open
osman-koc wants to merge 4 commits intof:masterfrom
osman-koc:feature/multi-links
Open

feat: Multi-platform link support (App Store / Google Play) + layout fixes#6
osman-koc wants to merge 4 commits intof:masterfrom
osman-koc:feature/multi-links

Conversation

@osman-koc
Copy link

@osman-koc osman-koc commented Mar 17, 2026

Multi-platform link support (App Store / Google Play) + layout fixes

Closes #5

Summary

Adds optional links array support to app entries, enabling mobile apps to expose multiple store links (App Store, Google Play, or any external URL) without duplicating app records. All changes are fully backward-compatible — existing app entries without links are unaffected.


Changes

app.js

New: platformIcon(platform)
Returns an SVG icon for "ios" (Apple), "android" (robot), or a generic external-link icon for anything else.

New: escapeHtml(str) / sanitizeUrl(url) / sanitizeIconContainerStyle(attrStr)
Security helpers added at module scope. escapeHtml HTML-encodes user-controlled strings before injection into innerHTML. sanitizeUrl validates that a URL uses http: or https: before rendering it as an href, blocking javascript: and other unsafe schemes. sanitizeIconContainerStyle (local to showLinksModal) strips ", ', <, > from inline style attribute values to prevent attribute injection.

Updated: getButtonLabel(app)
Returns "Get" when app.links is present, or when the app's category includes games / entertainment. Previous logic (brew / downloadUrl / installCommand) is preserved.

New: showLinksModal(app)
Opens a platform-selection modal when a "Get" button is clicked on an app row or featured banner. Uses the existing #modalOverlay / closeModal() infrastructure. Displays the app icon, name, and a list of platform links with icons and a chevron.

Updated: renderAppDetail(app)
When app.links is present and the app is not paid, wraps the "Get" button in a get-dropdown-wrapper and appends an animated get-dropdown panel listing each platform link (with escapeHtml/sanitizeUrl applied). The toggle button includes aria-expanded and aria-controls for accessibility. app.name and app.subtitle are also passed through escapeHtml. Paid apps with links fall through to the normal buy-button flow. Falls back to the original single button when links is absent.

Updated: bindEvents()
Get-button click priority order:

  1. Paid app → showBuyModal (unchanged)
  2. app.links (non-paid) + detail page → toggle dropdown
  3. app.links (non-paid) + list / featured → showLinksModal
  4. brew / installCommand → showBrewModal (unchanged)
  5. homepage / github (unchanged)

Updated: bindKeyboard() / outside-click handler
Escape key now also closes any open dropdown and resets aria-expanded to false. Added a document.click listener that closes open dropdowns and resets aria-expanded when clicking outside .get-dropdown-wrapper.


style.css

Layout fixes

Before After
body { overflow: hidden; width: 100vw } overflow removed, width: 100%
.app-store { overflow: hidden; max-width: 100vw } both removed / max-width: 100%
@600px section group had overflow: hidden removed
@600px .content-scroll { max-width: 100vw } max-width: 100%
@600px .app-detail-actions added justify-content: center

New CSS classes

Class Purpose
.modal-platform-links Wrapper list inside links modal
.modal-platform-link Single platform row (icon + label + chevron)
.modal-platform-icon / .modal-platform-label / .modal-platform-chevron Row sub-elements
.get-dropdown-wrapper Relative-positioned container for the detail-page dropdown
.get-dropdown Animated panel (opacity + transform, 0.18 s ease)
.get-dropdown.open Open state — full opacity, no transform offset
.get-dropdown-item Single link row inside dropdown
.get-dropdown-icon / .get-dropdown-label / .get-dropdown-arrow Row sub-elements

apps.json usage

No existing fields are modified. Add the optional links array to any app entry:

"links": [
  { "label": "App Store",   "url": "https://apps.apple.com/...",        "platform": "ios"     },
  { "label": "Google Play", "url": "https://play.google.com/store/...", "platform": "android" }
]

Supported platform values: "ios", "android", or any string (falls back to external-link icon).


Behavior overview

Context links absent links present
App row / featured "Get" unchanged opens platform-selection modal
App detail "Get" unchanged toggles animated dropdown below button
Escape / outside click unchanged also closes open dropdown
Screenshot 2026-03-17 at 05 58 49 Screenshot 2026-03-17 at 05 58 56 Screenshot 2026-03-17 at 05 59 09

Copilot AI review requested due to automatic review settings March 17, 2026 03:02
@osman-koc osman-koc changed the title feat(apps): implement platform icons and dropdown for app links feat: Multi-platform link support (App Store / Google Play) + layout fixes Mar 17, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for apps that provide multiple platform/download links by introducing a “Get” dropdown on the app detail page and a modal-based link picker elsewhere, alongside layout adjustments intended to reduce viewport-width overflow issues.

Changes:

  • Add platform-aware link rendering (dropdown on detail page; modal for list/other contexts) and supporting event handlers.
  • Update “Get/View” button labeling logic to treat apps with links (and some categories) as “Get”.
  • Adjust CSS viewport sizing (100vw100%), tweak mobile alignment, and add new styles for dropdown + modal link lists.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
style.css Reworks width/overflow constraints and adds styles for platform link UI (dropdown + modal link list), plus small mobile alignment tweaks.
app.js Adds platform icon rendering, link dropdown/modal UI, and click/keyboard behaviors for opening/closing platform link pickers.
Comments suppressed due to low confidence (1)

style.css:105

  • Removing overflow: hidden from body can introduce a second page-level scrollbar (especially on mobile, where .mobile-topbar + .content-scroll { height: 100vh; } exceed the viewport). If the intent is to fix horizontal overflow from 100vw, consider restoring overflow: hidden (or at least overflow-x: hidden) and/or adjusting the scroll container height (e.g., calc(100vh - var(--mobile-topbar-height))) so scrolling remains confined to .content-scroll.
body {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  height: 100vh;
  width: 100%;
  user-select: none;
  transition: background 0.3s ease, color 0.3s ease;
  overflow-wrap: break-word;
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for apps that have multiple platform-specific outbound links (e.g., iOS/Android/Web) by introducing a “Get” dropdown on the app detail page and a links modal for other contexts, along with layout/CSS tweaks to reduce horizontal overflow.

Changes:

  • Add HTML escaping and URL sanitization helpers, plus platform icon rendering, and wire them into new links UI.
  • Introduce a “Get” dropdown on the app detail page when app.links is present, and a modal to show platform links elsewhere.
  • Update CSS to prefer 100% widths over 100vw and add styling for the new dropdown and modal link list.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
style.css Adjusts width/overflow behavior and adds styles for the platform links modal and detail-page Get dropdown.
app.js Adds sanitization helpers and implements the multi-link Get dropdown + links modal behavior and event handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for multi-platform “Get” links (dropdown on detail view + modal elsewhere) and adjusts layout styles to reduce viewport-based overflow issues.

Changes:

  • Introduces HTML escaping + URL sanitization helpers and applies them to newly-rendered link UI.
  • Adds platform link dropdown (detail page) and a modal listing platform links (non-detail contexts).
  • Replaces several 100vw/overflow: hidden layout constraints with 100% sizing and adds a small mobile alignment tweak.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
style.css Updates viewport sizing/overflow rules and adds styles for the new platform-links modal and detail-page Get dropdown.
app.js Adds escaping/sanitization helpers, platform icon rendering, and link dropdown/modal behavior wired into the existing Get button flow.
Comments suppressed due to low confidence (1)

app.js:754

  • Now that sanitizeUrl() exists and is used for app.links, the remaining URL usages in this click handler still call window.open() with raw values from apps.json (app.homepage / app.github). For defense-in-depth (and consistency), route these through sanitizeUrl() as well (and consider skipping window.open if sanitization fails, rather than navigating to #).
        } else if (app.brew || app.installCommand) {
          showBrewModal(app);
        } else if (app.homepage) {
          window.open(app.homepage, "_blank");
        } else {
          window.open(app.github, "_blank");
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@osman-koc
Copy link
Author

@f can you review? Thanks.

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.

Minor iyileştirmeler ve çoklu link desteği

2 participants