-
Notifications
You must be signed in to change notification settings - Fork 0
Add allowedHosts configuration for dev server tunnel preview #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cfd98f2
72d7c3e
2cf6c70
00d61f0
3268f08
b2500c4
98697c2
f59f88f
d37032b
838546b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| NUXT_PUBLIC_APP_NAME="osu!dash" | ||
| NUXT_PUBLIC_OSU_API_BASE="https://osu.ppy.sh/api/v2" | ||
| NUXT_PUBLIC_OSU_TARGET_USER="Yourusername" | ||
| NUXT_OSU_CLIENT_ID="your_client_id" | ||
| NUXT_OSU_CLIENT_SECRET="your_client_secret" | ||
| OSU_REPLAY_PATH="/path/to/your/osu/exports" | ||
| NUXT_ENABLE_REPLAY_WATCHER="false" | ||
| NUXT_ENABLE_REPLAY_WATCHER="false" | ||
| NUXT_ALLOWED_HOSTS="osu.korpseluv.com" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||||||||||||||||||||||||||||||
| <script setup lang="ts"> | ||||||||||||||||||||||||||||||||||
| import { computed, onBeforeUnmount, onMounted, ref } from 'vue' | ||||||||||||||||||||||||||||||||||
| import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue' | ||||||||||||||||||||||||||||||||||
| import countryCodeList from 'flagpack-core/countryCodeList.json' | ||||||||||||||||||||||||||||||||||
| import BeatmapCover from '../components/BeatmapCover.vue' | ||||||||||||||||||||||||||||||||||
| import HitErrorBar from '../components/HitErrorBar.vue' | ||||||||||||||||||||||||||||||||||
|
|
@@ -81,7 +81,7 @@ const runtimeConfig = useRuntimeConfig() | |||||||||||||||||||||||||||||||||
| const appVersion = computed(() => String((runtimeConfig.public as any)?.gitHash || 'unknown')) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const fallbackUser: UserPayload = { | ||||||||||||||||||||||||||||||||||
| username: 'chlokun', | ||||||||||||||||||||||||||||||||||
| username: (runtimeConfig.public as any)?.osuTargetUser || 'chlokun', | ||||||||||||||||||||||||||||||||||
| avatar: 'https://a.ppy.sh/6829235?1680000000.jpeg', | ||||||||||||||||||||||||||||||||||
| rank: 852341, | ||||||||||||||||||||||||||||||||||
| pp: 1450, | ||||||||||||||||||||||||||||||||||
|
|
@@ -319,7 +319,7 @@ const modBadgeClass = (mod: string) => { | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const rankHistory = computed(() => user.value.rankHistory || []) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const chartRef = ref<HTMLElement | null>(null) | ||||||||||||||||||||||||||||||||||
| const chartRef = ref<SVGSVGElement | null>(null) | ||||||||||||||||||||||||||||||||||
| const graphHover = ref<{ | ||||||||||||||||||||||||||||||||||
| index: number | ||||||||||||||||||||||||||||||||||
| xPercent: number | ||||||||||||||||||||||||||||||||||
|
|
@@ -375,6 +375,42 @@ const tabs = [ | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const activeTab = ref<'overview' | 'top' | 'history' | 'deep'>('overview') | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Map URL hash to a tab id. Supports '#deep-stats' and '#deep'. | ||||||||||||||||||||||||||||||||||
| const mapHashToTab = (hash: string | null) => { | ||||||||||||||||||||||||||||||||||
| if (!hash) return null | ||||||||||||||||||||||||||||||||||
| const h = hash.startsWith('#') ? hash.slice(1) : hash | ||||||||||||||||||||||||||||||||||
| if (h === 'deep' || h === 'deep-stats') return 'deep' | ||||||||||||||||||||||||||||||||||
| if (h === 'overview') return 'overview' | ||||||||||||||||||||||||||||||||||
| if (h === 'top') return 'top' | ||||||||||||||||||||||||||||||||||
| if (h === 'history') return 'history' | ||||||||||||||||||||||||||||||||||
| return null | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const setTabFromHash = () => { | ||||||||||||||||||||||||||||||||||
| const t = mapHashToTab(typeof window !== 'undefined' ? window.location.hash : null) | ||||||||||||||||||||||||||||||||||
| if (t) activeTab.value = t | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| onMounted(() => { | ||||||||||||||||||||||||||||||||||
| // initialize from the fragment when the component mounts | ||||||||||||||||||||||||||||||||||
| setTabFromHash() | ||||||||||||||||||||||||||||||||||
| window.addEventListener('hashchange', setTabFromHash) | ||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| onBeforeUnmount(() => { | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+394
to
+400
|
||||||||||||||||||||||||||||||||||
| onMounted(() => { | |
| // initialize from the fragment when the component mounts | |
| setTabFromHash() | |
| window.addEventListener('hashchange', setTabFromHash) | |
| }) | |
| onBeforeUnmount(() => { | |
| onMounted(() => { | |
| if (typeof window === 'undefined') return | |
| // initialize from the fragment when the component mounts | |
| setTabFromHash() | |
| window.addEventListener('hashchange', setTabFromHash) | |
| }) | |
| onBeforeUnmount(() => { | |
| if (typeof window === 'undefined') return |
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The watch callback for activeTab changes the URL without checking if we're in a browser environment. While the watch will only run client-side in practice, the explicit window check on line 410 suggests defensive programming, but it's inconsistent with line 408 which doesn't check before calling history.replaceState. Consider adding a guard at the start of the watch callback to ensure window/history are available.
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback for DOMPoint when createSVGPoint is unavailable casts to 'any', which bypasses type safety. Consider defining a proper interface or type for the point object to maintain type safety, ensuring it has x, y properties and a matrixTransform method.
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are four levels of fallback logic for computing targetX (lines 650-678), with repeated code blocks computing the same rect-based calculation. Consider extracting the fallback calculation into a helper function to reduce duplication and improve maintainability.
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation appears to have changed from the original alignment. The opening div tag now has inconsistent indentation (extra spaces) compared to the surrounding code, which may indicate a formatting issue.
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 838 checks if badge.tone is NOT in the array ['badge-ss','badge-s'], but line 835-836 define styles for 'badge-ss' and 'badge-s'. The removed line 837 previously had a check for 'badge-a', which is now missing from line 838. If 'badge-a' is still a valid tone value, it will now incorrectly fall through to the default border styling instead of having its own specific styling.
| !['badge-ss','badge-s'].includes(badge.tone) && badge.label !== 'F' ? 'border border-white/30 text-white' : '' | |
| !['badge-ss','badge-s','badge-a'].includes(badge.tone) && badge.label !== 'F' ? 'border border-white/30 text-white' : '' |
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeline dot positioning changed from '-left-1.5 mt-0.5' to '-left-4 top-1/2 -translate-y-1/2'. This change shifts the dot 16px to the left (from -6px to -16px) and centers it vertically. Verify that there is sufficient left padding or margin in the parent container to accommodate the additional -10px shift, otherwise the dot may be clipped or overflow outside the visible area.
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional rendering logic 'score.deep_stats && openDetail(score)' on both click and keyup handlers will silently do nothing if deep_stats is falsy. For better accessibility and user feedback, consider disabling the interactive elements (removing role, tabindex, cursor-pointer) when deep_stats is not available, or providing visual feedback that the item is not clickable.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -52,8 +52,8 @@ export default defineNuxtConfig({ | |||||
| { name: 'viewport', content: 'width=device-width, initial-scale=1, user-scalable=no' } | ||||||
| ], | ||||||
| link: [ | ||||||
| { rel: 'icon', type: 'image/png', href: '/icon.png' }, | ||||||
| { rel: 'apple-touch-icon', href: '/icon.png' } | ||||||
| { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, | ||||||
| { rel: 'apple-touch-icon', href: '/favicon.ico' } | ||||||
| ] | ||||||
| } | ||||||
| }, | ||||||
|
|
@@ -78,6 +78,14 @@ export default defineNuxtConfig({ | |||||
| }, | ||||||
| vite: { | ||||||
| plugins: [tsconfigPaths()], | ||||||
| server: { | ||||||
| // allow hosts for previewing the dev server through a tunnel | ||||||
| // Can be set via env: `NUXT_ALLOWED_HOSTS` or `VITE_ALLOWED_HOSTS` (comma-separated). | ||||||
|
||||||
| allowedHosts: (process.env.NUXT_ALLOWED_HOSTS || process.env.VITE_ALLOWED_HOSTS || 'osu.korpseluv.com') | ||||||
|
||||||
| allowedHosts: (process.env.NUXT_ALLOWED_HOSTS || process.env.VITE_ALLOWED_HOSTS || 'osu.korpseluv.com') | |
| allowedHosts: (process.env.NUXT_ALLOWED_HOSTS || process.env.VITE_ALLOWED_HOSTS || 'localhost') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default value 'osu.korpseluv.com' in the .env.example file should match the intention of being an example. Consider using a placeholder like 'your-tunnel-domain.com' or 'example.com' instead of what appears to be a specific/personal domain.