@@ -23,35 +23,73 @@ import Modal from '~/components/Modal.vue';
2323export interface Props {
2424 open? : boolean ;
2525 t: ComposerTranslation ;
26+ // When provided, uses prop data instead of store data (for viewing release notes)
27+ release? : {
28+ version: string ;
29+ name? : string ;
30+ date? : string ;
31+ changelog? : string | null ;
32+ changelogPretty? : string ;
33+ sha256? : string | null ;
34+ } | null ;
2635}
2736
2837const props = withDefaults (defineProps <Props >(), {
2938 open: false ,
39+ release: null ,
3040});
3141
42+ const emit = defineEmits <{
43+ close: [];
44+ }>();
45+
3246const purchaseStore = usePurchaseStore ();
3347const updateOsStore = useUpdateOsStore ();
3448const themeStore = useThemeStore ();
35- const { darkMode } = storeToRefs (themeStore );
49+ const { darkMode, theme } = storeToRefs (themeStore );
50+ const isDarkMode = computed (() => {
51+ if (theme .value .name === ' azure' ) {
52+ return true ;
53+ }
54+ return darkMode .value ;
55+ });
3656const { availableWithRenewal, releaseForUpdate, changelogModalVisible } = storeToRefs (updateOsStore );
3757const { setReleaseForUpdate, fetchAndConfirmInstall } = updateOsStore ;
3858
59+ // Determine if we're in prop mode (viewing specific release) or store mode (update workflow)
60+ const isPropMode = computed (() => !! props .release );
61+
62+ // Use prop data when provided, store data when not
63+ const currentRelease = computed (() => props .release || releaseForUpdate .value );
64+
65+ // Modal visibility: use prop when in prop mode, store visibility when in store mode
66+ const modalVisible = computed (() => isPropMode .value ? props .open : changelogModalVisible .value );
67+
3968const showExtendKeyButton = computed (() => {
40- return availableWithRenewal .value ;
69+ return ! isPropMode . value && availableWithRenewal .value ;
4170});
4271
72+ // Handle modal closing - emit event in prop mode, clear store in store mode
73+ const handleClose = () => {
74+ if (isPropMode .value ) {
75+ emit (' close' );
76+ } else {
77+ setReleaseForUpdate (null );
78+ }
79+ };
80+
4381// iframe navigation handling
4482const iframeRef = ref <HTMLIFrameElement | null >(null );
4583const hasNavigated = ref (false );
4684const currentIframeUrl = ref <string | null >(null );
4785const actualIframeSrc = ref <string | null >(null );
4886
4987const docsChangelogUrl = computed (() => {
50- return releaseForUpdate .value ?.changelogPretty ?? null ;
88+ return currentRelease .value ?.changelogPretty ?? null ;
5189});
5290
5391const showRawChangelog = computed <boolean >(() => {
54- return ! docsChangelogUrl .value && !! releaseForUpdate .value ?.changelog ;
92+ return Boolean ( ! docsChangelogUrl .value && currentRelease .value ?.changelog ) ;
5593});
5694
5795const handleDocsPostMessages = (event : MessageEvent ) => {
@@ -80,7 +118,7 @@ const handleDocsPostMessages = (event: MessageEvent) => {
80118const sendThemeToIframe = () => {
81119 if (iframeRef .value && iframeRef .value .contentWindow ) {
82120 try {
83- const message = { type: ' theme-update' , theme: darkMode .value ? ' dark' : ' light' };
121+ const message = { type: ' theme-update' , theme: isDarkMode .value ? ' dark' : ' light' };
84122 iframeRef .value .contentWindow .postMessage (message , ' *' );
85123 } catch (error ) {
86124 console .error (' Failed to send theme to iframe:' , error );
@@ -120,7 +158,7 @@ watch(docsChangelogUrl, (newUrl) => {
120158});
121159
122160// Only need to watch for theme changes
123- watch (darkMode , () => {
161+ watch (isDarkMode , () => {
124162 // The iframe will only pick up the message if it has sent theme-ready
125163 sendThemeToIframe ();
126164});
@@ -129,16 +167,16 @@ watch(darkMode, () => {
129167
130168<template >
131169 <Modal
132- v-if =" releaseForUpdate ?.version"
170+ v-if =" currentRelease ?.version"
133171 :center-content =" false"
134172 max-width =" max-w-[800px]"
135- :open =" changelogModalVisible "
173+ :open =" modalVisible "
136174 :show-close-x =" true"
137175 :t =" t"
138176 :tall-content =" true"
139- :title =" t('Unraid OS {0} Changelog', [releaseForUpdate .version])"
177+ :title =" t('Unraid OS {0} Changelog', [currentRelease .version])"
140178 :disable-overlay-close =" false"
141- @close =" setReleaseForUpdate(null) "
179+ @close =" handleClose "
142180 >
143181 <template #main >
144182 <div class =" flex flex-col gap-4 min-w-[280px] sm:min-w-[400px]" >
@@ -156,12 +194,12 @@ watch(darkMode, () => {
156194
157195 <!-- Fallback to raw changelog -->
158196 <RawChangelogRenderer
159- v-else-if =" showRawChangelog && releaseForUpdate ?.changelog"
160- :changelog =" releaseForUpdate ?.changelog"
161- :version =" releaseForUpdate ?.version"
162- :date =" releaseForUpdate ?.date"
197+ v-else-if =" showRawChangelog && currentRelease ?.changelog"
198+ :changelog =" currentRelease ?.changelog"
199+ :version =" currentRelease ?.version"
200+ :date =" currentRelease ?.date"
163201 :t =" t"
164- :changelog-pretty =" releaseForUpdate ?.changelogPretty"
202+ :changelog-pretty =" currentRelease ?.changelogPretty"
165203 />
166204
167205 <!-- Loading state -->
@@ -189,32 +227,34 @@ watch(darkMode, () => {
189227
190228 <!-- View on docs button -->
191229 <BrandButton
192- v-if =" currentIframeUrl || releaseForUpdate ?.changelogPretty"
230+ v-if =" currentIframeUrl || currentRelease ?.changelogPretty"
193231 variant =" underline"
194232 :external =" true"
195- :href =" currentIframeUrl || releaseForUpdate ?.changelogPretty"
196- :icon =" ArrowTopRightOnSquareIcon"
233+ :href =" currentIframeUrl || currentRelease ?.changelogPretty"
234+ :icon-right =" ArrowTopRightOnSquareIcon"
197235 aria-label =" View on Docs"
198236 />
199237 </div >
200238
201- <!-- Action buttons -->
202- <BrandButton
203- v-if =" showExtendKeyButton"
204- :icon =" KeyIcon"
205- :icon-right =" ArrowTopRightOnSquareIcon"
206- @click =" purchaseStore.renew()"
207- >
208- {{ props.t('Extend License to Update') }}
209- </BrandButton >
210- <BrandButton
211- v-else-if =" releaseForUpdate?.sha256"
212- :icon =" ServerStackIcon"
213- :icon-right =" ArrowRightIcon"
214- @click =" fetchAndConfirmInstall(releaseForUpdate.sha256)"
215- >
216- {{ props.t('Continue') }}
217- </BrandButton >
239+ <!-- Action buttons (only in store mode for update workflow) -->
240+ <template v-if =" ! isPropMode " >
241+ <BrandButton
242+ v-if =" showExtendKeyButton"
243+ :icon =" KeyIcon"
244+ :icon-right =" ArrowTopRightOnSquareIcon"
245+ @click =" purchaseStore.renew()"
246+ >
247+ {{ props.t('Extend License to Update') }}
248+ </BrandButton >
249+ <BrandButton
250+ v-else-if =" currentRelease?.sha256"
251+ :icon =" ServerStackIcon"
252+ :icon-right =" ArrowRightIcon"
253+ @click =" fetchAndConfirmInstall(currentRelease.sha256)"
254+ >
255+ {{ props.t('Continue') }}
256+ </BrandButton >
257+ </template >
218258 </div >
219259 </template >
220260 </Modal >
0 commit comments