Files
bowlingManager/mobile/lib/utils/url_utils.dart
T
2025-10-23 22:04:03 +09:00

120 lines
4.3 KiB
Dart

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'test_utils.dart';
/// URL 관련 유틸리티 기능을 제공하는 클래스
class UrlUtils {
/// 이벤트 공개 URL의 기본 도메인 (프로덕션)
static const String eventBaseUrl = 'https://lanebow.com/events/';
/// 공개 URL 해시 생성
///
/// 8자리 영숫자 해시를 생성합니다.
/// 보안 및 충돌 방지를 위해 충분한 길이와 랜덤성을 가집니다.
/// 테스트 환경에서는 예측 가능한 해시를 반환합니다.
static String generatePublicHash() {
// 테스트 환경에서는 예측 가능한 해시 반환
if (TestUtils.isInTest) {
return TestUtils.getTestHash();
}
// 일반 환경에서는 랜덤 해시 생성
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
final random = Random();
return String.fromCharCodes(
Iterable.generate(
8,
(_) => chars.codeUnitAt(random.nextInt(chars.length)),
),
);
}
/// 이벤트 공개 URL 생성
///
/// [hash] 값을 기반으로 완전한 이벤트 공개 URL을 생성합니다.
static String getEventPublicUrl(String hash) {
return '$eventBaseUrl$hash';
}
/// URL을 클립보드에 복사하고 스낵바로 알림
///
/// [context]는 스낵바를 표시할 BuildContext입니다.
/// [url]은 복사할 URL 문자열입니다.
/// [duration]은 스낵바 표시 시간입니다. 기본값은 2초입니다.
static void copyUrlToClipboard(BuildContext context, String url, {Duration? duration}) {
Clipboard.setData(ClipboardData(text: url));
// 테스트 환경에서 안전하게 스낵바 표시
if (TestUtils.isInTest) {
// 테스트 환경에서는 로그만 출력
debugPrint('클립보드에 URL 복사됨: $url');
return;
}
// 일반 환경에서는 스낵바 표시
SchedulerBinding.instance.addPostFrameCallback((_) {
if (context.mounted) {
final snackBar = SnackBar(
content: const Text('공개 URL이 클립보드에 복사되었습니다'),
action: SnackBarAction(
label: '확인',
onPressed: () {},
),
duration: duration ?? const Duration(seconds: 2),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
});
}
/// 해시 생성/재생성 후 스낵바로 알림
///
/// [context]는 스낵바를 표시할 BuildContext입니다.
/// [isNew]는 새로 생성된 해시인지 여부입니다. true면 생성, false면 재생성 메시지를 표시합니다.
/// [hash]는 생성된 해시 값입니다.
///
/// 주의: 이 메서드는 더 이상 직접 사용하지 않습니다. 테스트 환경에서 문제가 발생할 수 있습니다.
/// 대신 각 화면에서 직접 스낵바를 표시하는 것이 좋습니다.
@Deprecated('테스트 환경에서 문제가 발생할 수 있습니다. 대신 각 화면에서 직접 스낵바를 표시하세요.')
static void showHashGenerationSnackbar(BuildContext context, bool isNew, String hash) {
final message = isNew
? '공개 URL 해시가 생성되었습니다'
: '공개 URL 해시가 재생성되었습니다. 이전 URL은 더 이상 유효하지 않습니다';
final url = getEventPublicUrl(hash);
// 테스트 환경에서는 항상 로그만 출력
if (TestUtils.isInTest) {
debugPrint('해시 생성 완료: $message, URL: $url');
return;
}
// 일반 환경에서는 스낵바 표시 (context가 유효한지 확인)
if (context.mounted) {
SchedulerBinding.instance.addPostFrameCallback((_) {
if (context.mounted) {
try {
final snackBar = SnackBar(
content: Text(message),
action: SnackBarAction(
label: 'URL 복사',
onPressed: () => copyUrlToClipboard(context, url),
),
duration: const Duration(seconds: 4),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} catch (e) {
debugPrint('스낵바 표시 오류: $e');
}
}
});
}
}
}