[Claude Code Desktop 자동 설치 환경]
- setup/CLAUDE.md: 트리거 키워드 + 설치 패키지 설명
- setup/.claude/skills/guardia-install/SKILL.md: 6단계 설치 오케스트레이터
Phase 0: 의도 파악 → Phase 1: OS 감지 → Phase 2: 사전 확인
Phase 3: 설치 실행 → Phase 4: 라이선스 발급 → Phase 5: 검증 → Phase 6: 완료보고
[통합 자동 설치 스크립트]
- setup/install_auto.sh: Linux 통합 (OS 자동 감지 ubuntu/centos/rhel)
- --license trial30|trial7|<key> 파라미터
- 설치 완료 후 GUARDiA 자동 실행 + 브라우저 자동 열기
- --test 검증 모드
- setup/install_auto.ps1: Windows 통합 (ASCII 전용, PS 5.1 호환)
- 설치 후 NSSM 서비스 자동 시작 + 브라우저 자동 열기
- -Test 파라미터로 검증 전용 실행
[라이선스 엔진 개선]
- core/license.py: generate_trial_key(days=None) 파라미터 추가
- TRIAL_DURATION_DAYS = TRIAL_DURATION_DAYS 환경변수로 조정 가능
- routers/license.py: TrialRequest.days 필드 + 30일 체험판 지원
POST /api/license/trial {"days": 30} 로 30일 발급
사용자 경험:
1. setup/ 폴더를 새 PC에 복사
2. Claude Code Desktop 열고 해당 폴더 open
3. "GUARDiA 시스템 1달 사용자로 설치해 줘" 입력
4. 자동으로 OS 감지 → 설치 → 30일 라이선스 → 브라우저 열림
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
305 lines
9.0 KiB
JavaScript
305 lines
9.0 KiB
JavaScript
import { g as getDocument } from '../shared/ssr-window.esm.mjs';
|
|
|
|
/* eslint no-underscore-dangle: "off" */
|
|
/* eslint no-use-before-define: "off" */
|
|
function Autoplay(_ref) {
|
|
let {
|
|
swiper,
|
|
extendParams,
|
|
on,
|
|
emit,
|
|
params
|
|
} = _ref;
|
|
swiper.autoplay = {
|
|
running: false,
|
|
paused: false,
|
|
timeLeft: 0
|
|
};
|
|
extendParams({
|
|
autoplay: {
|
|
enabled: false,
|
|
delay: 3000,
|
|
waitForTransition: true,
|
|
disableOnInteraction: false,
|
|
stopOnLastSlide: false,
|
|
reverseDirection: false,
|
|
pauseOnMouseEnter: false
|
|
}
|
|
});
|
|
let timeout;
|
|
let raf;
|
|
let autoplayDelayTotal = params && params.autoplay ? params.autoplay.delay : 3000;
|
|
let autoplayDelayCurrent = params && params.autoplay ? params.autoplay.delay : 3000;
|
|
let autoplayTimeLeft;
|
|
let autoplayStartTime = new Date().getTime();
|
|
let wasPaused;
|
|
let isTouched;
|
|
let pausedByTouch;
|
|
let touchStartTimeout;
|
|
let slideChanged;
|
|
let pausedByInteraction;
|
|
let pausedByPointerEnter;
|
|
function onTransitionEnd(e) {
|
|
if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
|
|
if (e.target !== swiper.wrapperEl) return;
|
|
swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
|
|
if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {
|
|
return;
|
|
}
|
|
resume();
|
|
}
|
|
const calcTimeLeft = () => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
if (swiper.autoplay.paused) {
|
|
wasPaused = true;
|
|
} else if (wasPaused) {
|
|
autoplayDelayCurrent = autoplayTimeLeft;
|
|
wasPaused = false;
|
|
}
|
|
const timeLeft = swiper.autoplay.paused ? autoplayTimeLeft : autoplayStartTime + autoplayDelayCurrent - new Date().getTime();
|
|
swiper.autoplay.timeLeft = timeLeft;
|
|
emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal);
|
|
raf = requestAnimationFrame(() => {
|
|
calcTimeLeft();
|
|
});
|
|
};
|
|
const getSlideDelay = () => {
|
|
let activeSlideEl;
|
|
if (swiper.virtual && swiper.params.virtual.enabled) {
|
|
activeSlideEl = swiper.slides.find(slideEl => slideEl.classList.contains('swiper-slide-active'));
|
|
} else {
|
|
activeSlideEl = swiper.slides[swiper.activeIndex];
|
|
}
|
|
if (!activeSlideEl) return undefined;
|
|
const currentSlideDelay = parseInt(activeSlideEl.getAttribute('data-swiper-autoplay'), 10);
|
|
return currentSlideDelay;
|
|
};
|
|
const run = delayForce => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
cancelAnimationFrame(raf);
|
|
calcTimeLeft();
|
|
let delay = typeof delayForce === 'undefined' ? swiper.params.autoplay.delay : delayForce;
|
|
autoplayDelayTotal = swiper.params.autoplay.delay;
|
|
autoplayDelayCurrent = swiper.params.autoplay.delay;
|
|
const currentSlideDelay = getSlideDelay();
|
|
if (!Number.isNaN(currentSlideDelay) && currentSlideDelay > 0 && typeof delayForce === 'undefined') {
|
|
delay = currentSlideDelay;
|
|
autoplayDelayTotal = currentSlideDelay;
|
|
autoplayDelayCurrent = currentSlideDelay;
|
|
}
|
|
autoplayTimeLeft = delay;
|
|
const speed = swiper.params.speed;
|
|
const proceed = () => {
|
|
if (!swiper || swiper.destroyed) return;
|
|
if (swiper.params.autoplay.reverseDirection) {
|
|
if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) {
|
|
swiper.slidePrev(speed, true, true);
|
|
emit('autoplay');
|
|
} else if (!swiper.params.autoplay.stopOnLastSlide) {
|
|
swiper.slideTo(swiper.slides.length - 1, speed, true, true);
|
|
emit('autoplay');
|
|
}
|
|
} else {
|
|
if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) {
|
|
swiper.slideNext(speed, true, true);
|
|
emit('autoplay');
|
|
} else if (!swiper.params.autoplay.stopOnLastSlide) {
|
|
swiper.slideTo(0, speed, true, true);
|
|
emit('autoplay');
|
|
}
|
|
}
|
|
if (swiper.params.cssMode) {
|
|
autoplayStartTime = new Date().getTime();
|
|
requestAnimationFrame(() => {
|
|
run();
|
|
});
|
|
}
|
|
};
|
|
if (delay > 0) {
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(() => {
|
|
proceed();
|
|
}, delay);
|
|
} else {
|
|
requestAnimationFrame(() => {
|
|
proceed();
|
|
});
|
|
}
|
|
|
|
// eslint-disable-next-line
|
|
return delay;
|
|
};
|
|
const start = () => {
|
|
autoplayStartTime = new Date().getTime();
|
|
swiper.autoplay.running = true;
|
|
run();
|
|
emit('autoplayStart');
|
|
};
|
|
const stop = () => {
|
|
swiper.autoplay.running = false;
|
|
clearTimeout(timeout);
|
|
cancelAnimationFrame(raf);
|
|
emit('autoplayStop');
|
|
};
|
|
const pause = (internal, reset) => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
clearTimeout(timeout);
|
|
if (!internal) {
|
|
pausedByInteraction = true;
|
|
}
|
|
const proceed = () => {
|
|
emit('autoplayPause');
|
|
if (swiper.params.autoplay.waitForTransition) {
|
|
swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd);
|
|
} else {
|
|
resume();
|
|
}
|
|
};
|
|
swiper.autoplay.paused = true;
|
|
if (reset) {
|
|
if (slideChanged) {
|
|
autoplayTimeLeft = swiper.params.autoplay.delay;
|
|
}
|
|
slideChanged = false;
|
|
proceed();
|
|
return;
|
|
}
|
|
const delay = autoplayTimeLeft || swiper.params.autoplay.delay;
|
|
autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime);
|
|
if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) return;
|
|
if (autoplayTimeLeft < 0) autoplayTimeLeft = 0;
|
|
proceed();
|
|
};
|
|
const resume = () => {
|
|
if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop || swiper.destroyed || !swiper.autoplay.running) return;
|
|
autoplayStartTime = new Date().getTime();
|
|
if (pausedByInteraction) {
|
|
pausedByInteraction = false;
|
|
run(autoplayTimeLeft);
|
|
} else {
|
|
run();
|
|
}
|
|
swiper.autoplay.paused = false;
|
|
emit('autoplayResume');
|
|
};
|
|
const onVisibilityChange = () => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
const document = getDocument();
|
|
if (document.visibilityState === 'hidden') {
|
|
pausedByInteraction = true;
|
|
pause(true);
|
|
}
|
|
if (document.visibilityState === 'visible') {
|
|
resume();
|
|
}
|
|
};
|
|
const onPointerEnter = e => {
|
|
if (e.pointerType !== 'mouse') return;
|
|
pausedByInteraction = true;
|
|
pausedByPointerEnter = true;
|
|
if (swiper.animating || swiper.autoplay.paused) return;
|
|
pause(true);
|
|
};
|
|
const onPointerLeave = e => {
|
|
if (e.pointerType !== 'mouse') return;
|
|
pausedByPointerEnter = false;
|
|
if (swiper.autoplay.paused) {
|
|
resume();
|
|
}
|
|
};
|
|
const attachMouseEvents = () => {
|
|
if (swiper.params.autoplay.pauseOnMouseEnter) {
|
|
swiper.el.addEventListener('pointerenter', onPointerEnter);
|
|
swiper.el.addEventListener('pointerleave', onPointerLeave);
|
|
}
|
|
};
|
|
const detachMouseEvents = () => {
|
|
if (swiper.el && typeof swiper.el !== 'string') {
|
|
swiper.el.removeEventListener('pointerenter', onPointerEnter);
|
|
swiper.el.removeEventListener('pointerleave', onPointerLeave);
|
|
}
|
|
};
|
|
const attachDocumentEvents = () => {
|
|
const document = getDocument();
|
|
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
};
|
|
const detachDocumentEvents = () => {
|
|
const document = getDocument();
|
|
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
};
|
|
on('init', () => {
|
|
if (swiper.params.autoplay.enabled) {
|
|
attachMouseEvents();
|
|
attachDocumentEvents();
|
|
start();
|
|
}
|
|
});
|
|
on('destroy', () => {
|
|
detachMouseEvents();
|
|
detachDocumentEvents();
|
|
if (swiper.autoplay.running) {
|
|
stop();
|
|
}
|
|
});
|
|
on('_freeModeStaticRelease', () => {
|
|
if (pausedByTouch || pausedByInteraction) {
|
|
resume();
|
|
}
|
|
});
|
|
on('_freeModeNoMomentumRelease', () => {
|
|
if (!swiper.params.autoplay.disableOnInteraction) {
|
|
pause(true, true);
|
|
} else {
|
|
stop();
|
|
}
|
|
});
|
|
on('beforeTransitionStart', (_s, speed, internal) => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
if (internal || !swiper.params.autoplay.disableOnInteraction) {
|
|
pause(true, true);
|
|
} else {
|
|
stop();
|
|
}
|
|
});
|
|
on('sliderFirstMove', () => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
if (swiper.params.autoplay.disableOnInteraction) {
|
|
stop();
|
|
return;
|
|
}
|
|
isTouched = true;
|
|
pausedByTouch = false;
|
|
pausedByInteraction = false;
|
|
touchStartTimeout = setTimeout(() => {
|
|
pausedByInteraction = true;
|
|
pausedByTouch = true;
|
|
pause(true);
|
|
}, 200);
|
|
});
|
|
on('touchEnd', () => {
|
|
if (swiper.destroyed || !swiper.autoplay.running || !isTouched) return;
|
|
clearTimeout(touchStartTimeout);
|
|
clearTimeout(timeout);
|
|
if (swiper.params.autoplay.disableOnInteraction) {
|
|
pausedByTouch = false;
|
|
isTouched = false;
|
|
return;
|
|
}
|
|
if (pausedByTouch && swiper.params.cssMode) resume();
|
|
pausedByTouch = false;
|
|
isTouched = false;
|
|
});
|
|
on('slideChange', () => {
|
|
if (swiper.destroyed || !swiper.autoplay.running) return;
|
|
slideChanged = true;
|
|
});
|
|
Object.assign(swiper.autoplay, {
|
|
start,
|
|
stop,
|
|
pause,
|
|
resume
|
|
});
|
|
}
|
|
|
|
export { Autoplay as default };
|