Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

NotchMyProblem Icon

NotchMyProblem

Swift package that handles positioning UI elements around the iPhone's notch or Dynamic Island.

Swift 6.0+iOS 13+License: MIT

iPhone with notchiPhone with Dynamic IslandiPhone without notch
Notch DevicesDynamic IslandStandard Devices
iPhone X → 14/Plus, 16eiPhone 14 Pro+, 15/16/17 series, AirHome button iPhones, iPads, Mac

Overview

NotchMyProblem automatically detects the device's top cutout and provides tools to create adaptive layouts without manual positioning.

  • Automatically positions buttons around the notch or Dynamic Island
  • Adapts to device-specific dimensions with built-in overrides
  • Supports all modern iPhones: notch (iPhone X → 14/Plus, 16e), Dynamic Island (14 Pro+, 15/16/17 series, Air), and standard devices
  • Intelligent padding system that scales with cutout size

Installation

dependencies:[.package(url:"https://github.com/Aeastr/NotchMyProblem.git", from:"2.0.0")]
import NotchMyProblem

Or in Xcode: File > Add Packages… and enter https://github.com/Aeastr/NotchMyProblem

Usage

CutoutAccessoryView

The simplest way to position UI elements around the notch/island:

structMyView:View{varbody:someView{ZStack{
// Your main content here
CutoutAccessoryView(
padding:.auto,
leadingContent:{Button(action:{print("Left tapped")}){Image(systemName:"gear")}},
trailingContent:{Button(action:{print("Right tapped")}){Text("Save")}})}}}

Manual Access

Access cutout dimensions directly when needed:

letrawRect=NotchMyProblem.exclusionRect // raw API result
letadjusted=NotchMyProblem.shared.adjustedExclusionRect // with overrides applied
letcustomRect=NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)

Customization

Padding

Without proper padding, UI elements can appear cramped against the cutout, get clipped by curved screen edges, or look inconsistent across devices. NotchMyProblem's padding scales with actual cutout dimensions to keep content at a safe, polished distance.

Three padding types:

  • Cutout padding – space around the display cutout
  • Content padding – space on either side of your HStack content
  • Vertical padding – space above and below your content

Available modes:

ModeDescription
.autoAdaptive padding using an inverse relationship—narrow cutouts (Dynamic Island) get more breathing room, wide cutouts (notch) get less since they already create natural spacing.
.noneNo extra padding; views hug the safe-area edges exactly.
.custom(cutout:content:vertical:)Supply closures to compute each padding dynamically.
CutoutAccessoryView(
padding:.custom(
cutout:{ cutoutW in cutoutW /12},
content:{ cutoutW in cutoutW /6},
vertical:{ cutoutH in cutoutH *0.2}),
leadingContent:{ /* … */ },
trailingContent:{ /* … */ })

Device Overrides

Some devices report incorrect notch dimensions through the API, causing misaligned UI:

Misaligned buttons on iPhone 16e without overrides

NotchMyProblem includes built-in overrides (e.g., iPhone 16e), but you can configure your own:

Global overrides (app-wide):

NotchMyProblem.globalOverrides =[.series(prefix:"iPhone13", scale:0.95, heightFactor:1.0, radius:27),DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

Instance overrides:

NotchMyProblem.shared.overrides =[DeviceOverride(modelIdentifier:"iPhone14,3", scale:0.8, heightFactor:0.7)]

View-specific overrides:

CutoutAccessoryView(/* … */).notchOverride(.series(prefix:"iPhone14", scale:0.6, heightFactor:0.6))

Override precedence: View-specific → Instance exact → Instance series → Global exact → Global series

How It Works

NotchMyProblem uses private APIs to detect the device's display cutout dimensions. Filter Console with subsystem com.notchmyproblem for debug logs.

Built on concepts from TopNotch. Uses private APIs—use at your own risk.

Device Testing

ModelDynamic IslandTested
iPhone 17YesYes
iPhone 17 ProYesYes
iPhone 17 Pro MaxYesYes
iPhone AirYesYes

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Position content around the iPhone's notch or Dynamic Island.

Resources

Code of conduct

Contributing

Stars

364 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages