Files
api/web/components/Activation/store/activationCodeModal.ts
Eli Bosley 39e83b2aa1 feat: move activation code logic into the API (#1369)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added comprehensive activation code customization service with dynamic
theming, partner branding, and UI updates.
- Introduced new GraphQL types and public queries for activation code,
partner info, and theme data.
- Implemented new web UI stores and components for activation modal,
partner logos, and theme management.
- **Improvements**
- Removed legacy activation code scripts, PHP components, and plugin
references, streamlining activation logic.
- Enhanced configuration and environment support for activation and
theming features.
- Improved error handling, validation, and type safety in activation and
customization modules.
- **Bug Fixes**
- Fixed color code validation and path handling in customization
service.
- **Chores**
  - Added pre-commit linting hooks and related configuration.
  - Cleaned up test and development environment files.
- **Tests**
- Added extensive tests covering activation customization service
initialization, data handling, and file modifications.
  - Removed obsolete tests related to legacy activation code store.
- **Refactor**
- Migrated activation and partner branding logic from legacy scripts and
PHP to TypeScript services and GraphQL resolvers.
- Reorganized store and component architecture for activation-related
features.
- **Style**
- Updated UI components for improved branding, theming, accessibility,
and layout consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Zack Spear <hi@zackspear.com>
2025-05-01 17:40:36 -04:00

83 lines
2.4 KiB
TypeScript

import { computed, onMounted, onUnmounted } from 'vue';
import { createPinia, defineStore, setActivePinia, storeToRefs } from 'pinia';
import { useSessionStorage } from '@vueuse/core';
import { ACTIVATION_CODE_MODAL_HIDDEN_STORAGE_KEY } from '~/consts';
import { useActivationCodeDataStore } from '~/components/Activation/store/activationCodeData';
import { useCallbackActionsStore } from '~/store/callbackActions';
setActivePinia(createPinia()); /** required in web component context */
export const useActivationCodeModalStore = defineStore('activationCodeModal', () => {
const isHidden = useSessionStorage<boolean | null>(ACTIVATION_CODE_MODAL_HIDDEN_STORAGE_KEY, null);
const { isFreshInstall } = storeToRefs(useActivationCodeDataStore());
const { callbackData } = storeToRefs(useCallbackActionsStore());
const setIsHidden = (value: boolean | null) => {
isHidden.value = value;
};
/**
* Should only see this if
* 1. It's explicitly set to show (isHidden === false)
* OR
* 2. It's a fresh server install where no keyfile has been present before
* 3. there's not callback data
* 4. it's not been explicitly hidden (isHidden === null)
*/
const isVisible = computed<boolean>(() => {
// Force show if explicitly set to false
if (isHidden.value === false) {
return true;
}
// Default visibility logic (show if not explicitly hidden AND fresh install AND no callback data)
return isHidden.value === null && isFreshInstall.value && !callbackData.value;
});
/**
* Listen for konami code sequence to close the modal
*/
const keySequence = [
'ArrowUp',
'ArrowUp',
'ArrowDown',
'ArrowDown',
'ArrowLeft',
'ArrowRight',
'ArrowLeft',
'ArrowRight',
'b',
'a',
];
let sequenceIndex = 0;
const handleKeydown = (event: KeyboardEvent) => {
if (event.key === keySequence[sequenceIndex]) {
sequenceIndex++;
} else {
sequenceIndex = 0;
}
if (sequenceIndex === keySequence.length) {
setIsHidden(true);
// Redirect only if explicitly hidden via konami code, not just closed normally
window.location.href = '/Tools/Registration';
}
};
onMounted(() => {
window?.addEventListener('keydown', handleKeydown);
});
onUnmounted(() => {
window?.removeEventListener('keydown', handleKeydown);
});
return {
isVisible,
setIsHidden,
};
});