앱 위젯에서 구분선 리사이즈 안되는 문제 수정

This commit is contained in:
Macbook
2026-06-14 17:54:26 +09:00
parent 7f5e7b22d2
commit ead2ba6b3a
9 changed files with 229 additions and 65 deletions
+1
View File
@@ -14,6 +14,7 @@
"dependencies": {
"@capacitor/android": "^7.0.0",
"@capacitor/app": "^7.0.0",
"@capacitor/browser": "^7.0.5",
"@capacitor/core": "^7.0.0",
"@capacitor/haptics": "^7.0.0",
"@capacitor/ios": "^7.0.0",
+69 -9
View File
@@ -2,7 +2,9 @@
* Android 앱 내 업데이트 — /api/mobile-app/info 버전 비교 후 APK 다운로드
*/
import { App } from '@capacitor/app';
import { Browser } from '@capacitor/browser';
import { Capacitor } from '@capacitor/core';
import { Preferences } from '@capacitor/preferences';
import {
isRemoteVersionNewer,
loadMobileAppReleaseInfo,
@@ -16,7 +18,8 @@ export interface AppUpdateCheckResult {
release?: MobileAppReleaseInfoDto | null;
}
const skipKey = (remote: string) => `gc_skip_update_${remote}`;
const skipSessionKey = (remote: string) => `gc_skip_update_${remote}`;
const pendingInstallKey = 'gc_pending_update_install';
export async function getCurrentAppVersion(): Promise<string> {
if (!Capacitor.isNativePlatform()) {
@@ -30,10 +33,49 @@ export async function getCurrentAppVersion(): Promise<string> {
}
}
async function getPendingInstallVersion(): Promise<string | null> {
try {
const { value } = await Preferences.get({ key: pendingInstallKey });
return value?.trim() || null;
} catch {
return null;
}
}
async function setPendingInstallVersion(remoteVersion: string): Promise<void> {
try {
await Preferences.set({ key: pendingInstallKey, value: remoteVersion });
} catch {
/* ignore */
}
}
async function clearPendingInstallVersion(): Promise<void> {
try {
await Preferences.remove({ key: pendingInstallKey });
} catch {
/* ignore */
}
}
/** 설치 완료 시 pending 플래그 제거 */
async function reconcilePendingInstall(currentVersion: string, remoteVersion?: string): Promise<void> {
const pending = await getPendingInstallVersion();
if (!pending) return;
if (remoteVersion && !isRemoteVersionNewer(currentVersion, remoteVersion)) {
await clearPendingInstallVersion();
return;
}
if (!isRemoteVersionNewer(currentVersion, pending)) {
await clearPendingInstallVersion();
}
}
export async function checkForAppUpdate(): Promise<AppUpdateCheckResult> {
const currentVersion = await getCurrentAppVersion();
const release = await loadMobileAppReleaseInfo();
const remoteVersion = release?.version?.trim();
await reconcilePendingInstall(currentVersion, remoteVersion);
const updateAvailable = Boolean(
release?.available
&& remoteVersion
@@ -49,14 +91,19 @@ export async function openApkDownload(release?: MobileAppReleaseInfoDto | null):
if (!url) return false;
if (Capacitor.isNativePlatform() && Capacitor.getPlatform() === 'android') {
const opened = window.open(url, '_blank', 'noopener,noreferrer');
if (opened) return true;
try {
await Browser.open({ url, presentationStyle: 'popover' });
return true;
} catch {
/* Browser 플러그인 실패 시 anchor fallback */
}
}
const a = document.createElement('a');
a.href = url;
a.rel = 'noopener';
a.download = info?.fileName ?? 'goldenchart-android.apk';
a.target = '_blank';
document.body.appendChild(a);
a.click();
a.remove();
@@ -65,7 +112,7 @@ export async function openApkDownload(release?: MobileAppReleaseInfoDto | null):
export function isUpdateDismissed(remoteVersion: string): boolean {
try {
return sessionStorage.getItem(skipKey(remoteVersion)) === '1';
return sessionStorage.getItem(skipSessionKey(remoteVersion)) === '1';
} catch {
return false;
}
@@ -73,13 +120,24 @@ export function isUpdateDismissed(remoteVersion: string): boolean {
export function dismissUpdate(remoteVersion: string): void {
try {
sessionStorage.setItem(skipKey(remoteVersion), '1');
sessionStorage.setItem(skipSessionKey(remoteVersion), '1');
} catch {
/* ignore */
}
}
/** 업데이트 확인 후 confirm → APK 다운로드. skipIfDismissed면 세션 내 거부 버전 생략 */
/** 다운로드 시작 후 같은 버전 재알림 방지 (설치 완료 전) */
export async function isUpdatePendingInstall(remoteVersion: string): Promise<boolean> {
const pending = await getPendingInstallVersion();
return pending === remoteVersion;
}
export async function shouldSkipUpdatePrompt(remoteVersion: string): Promise<boolean> {
if (isUpdateDismissed(remoteVersion)) return true;
return isUpdatePendingInstall(remoteVersion);
}
/** 업데이트 확인 후 confirm → APK 다운로드. skipIfDismissed면 세션 거부·다운로드 대기 중 생략 */
export async function promptAppUpdate(options?: {
skipIfDismissed?: boolean;
}): Promise<boolean> {
@@ -92,7 +150,7 @@ export async function promptAppUpdate(options?: {
return false;
}
if (options?.skipIfDismissed && isUpdateDismissed(check.remoteVersion)) {
if (options?.skipIfDismissed && await shouldSkipUpdatePrompt(check.remoteVersion)) {
return false;
}
@@ -107,11 +165,12 @@ export async function promptAppUpdate(options?: {
return false;
}
await setPendingInstallVersion(check.remoteVersion);
await openApkDownload(check.release);
return true;
}
/** 설정 화면 — 수동 업데이트 확인 */
/** 설정 화면 — 수동 업데이트 확인 (pending 스킵 무시) */
export async function checkAndPromptAppUpdate(): Promise<AppUpdateCheckResult> {
const result = await checkForAppUpdate();
if (!result.updateAvailable) {
@@ -122,7 +181,8 @@ export async function checkAndPromptAppUpdate(): Promise<AppUpdateCheckResult> {
`새 버전 v${result.remoteVersion} 사용 가능.\n`
+ `현재 v${result.currentVersion}\n\nAPK를 다운로드하시겠습니까?`,
);
if (ok) {
if (ok && result.remoteVersion) {
await setPendingInstallVersion(result.remoteVersion);
await openApkDownload(result.release);
}
return result;