Line data Source code
1 : import 'dart:math';
2 :
3 : import 'package:flutter/material.dart';
4 : import 'package:flutter/scheduler.dart';
5 : import 'package:flutter/services.dart';
6 :
7 : import 'test_utils.dart';
8 :
9 : /// URL 관련 유틸리티 기능을 제공하는 클래스
10 : class UrlUtils {
11 : /// 이벤트 공개 URL의 기본 도메인
12 : static const String eventBaseUrl = 'https://bowling.example.com/events/';
13 :
14 : /// 공개 URL 해시 생성
15 : ///
16 : /// 8자리 영숫자 해시를 생성합니다.
17 : /// 보안 및 충돌 방지를 위해 충분한 길이와 랜덤성을 가집니다.
18 : /// 테스트 환경에서는 예측 가능한 해시를 반환합니다.
19 1 : static String generatePublicHash() {
20 : // 테스트 환경에서는 예측 가능한 해시 반환
21 1 : if (TestUtils.isInTest) {
22 1 : return TestUtils.getTestHash();
23 : }
24 :
25 : // 일반 환경에서는 랜덤 해시 생성
26 : const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
27 0 : final random = Random();
28 0 : return String.fromCharCodes(
29 0 : Iterable.generate(
30 : 8,
31 0 : (_) => chars.codeUnitAt(random.nextInt(chars.length)),
32 : ),
33 : );
34 : }
35 :
36 : /// 이벤트 공개 URL 생성
37 : ///
38 : /// [hash] 값을 기반으로 완전한 이벤트 공개 URL을 생성합니다.
39 0 : static String getEventPublicUrl(String hash) {
40 0 : return '$eventBaseUrl$hash';
41 : }
42 :
43 : /// URL을 클립보드에 복사하고 스낵바로 알림
44 : ///
45 : /// [context]는 스낵바를 표시할 BuildContext입니다.
46 : /// [url]은 복사할 URL 문자열입니다.
47 : /// [duration]은 스낵바 표시 시간입니다. 기본값은 2초입니다.
48 0 : static void copyUrlToClipboard(BuildContext context, String url, {Duration? duration}) {
49 0 : Clipboard.setData(ClipboardData(text: url));
50 :
51 : // 테스트 환경에서 안전하게 스낵바 표시
52 0 : if (TestUtils.isInTest) {
53 : // 테스트 환경에서는 로그만 출력
54 0 : debugPrint('클립보드에 URL 복사됨: $url');
55 : return;
56 : }
57 :
58 : // 일반 환경에서는 스낵바 표시
59 0 : SchedulerBinding.instance.addPostFrameCallback((_) {
60 0 : if (context.mounted) {
61 0 : final snackBar = SnackBar(
62 : content: const Text('공개 URL이 클립보드에 복사되었습니다'),
63 0 : action: SnackBarAction(
64 : label: '확인',
65 0 : onPressed: () {},
66 : ),
67 : duration: duration ?? const Duration(seconds: 2),
68 : );
69 :
70 0 : ScaffoldMessenger.of(context).showSnackBar(snackBar);
71 : }
72 : });
73 : }
74 :
75 : /// 해시 생성/재생성 후 스낵바로 알림
76 : ///
77 : /// [context]는 스낵바를 표시할 BuildContext입니다.
78 : /// [isNew]는 새로 생성된 해시인지 여부입니다. true면 생성, false면 재생성 메시지를 표시합니다.
79 : /// [hash]는 생성된 해시 값입니다.
80 : ///
81 : /// 주의: 이 메서드는 더 이상 직접 사용하지 않습니다. 테스트 환경에서 문제가 발생할 수 있습니다.
82 : /// 대신 각 화면에서 직접 스낵바를 표시하는 것이 좋습니다.
83 0 : @Deprecated('테스트 환경에서 문제가 발생할 수 있습니다. 대신 각 화면에서 직접 스낵바를 표시하세요.')
84 : static void showHashGenerationSnackbar(BuildContext context, bool isNew, String hash) {
85 : final message = isNew
86 : ? '공개 URL 해시가 생성되었습니다'
87 : : '공개 URL 해시가 재생성되었습니다. 이전 URL은 더 이상 유효하지 않습니다';
88 :
89 0 : final url = getEventPublicUrl(hash);
90 :
91 : // 테스트 환경에서는 항상 로그만 출력
92 0 : if (TestUtils.isInTest) {
93 0 : debugPrint('해시 생성 완료: $message, URL: $url');
94 : return;
95 : }
96 :
97 : // 일반 환경에서는 스낵바 표시 (context가 유효한지 확인)
98 0 : if (context.mounted) {
99 0 : SchedulerBinding.instance.addPostFrameCallback((_) {
100 0 : if (context.mounted) {
101 : try {
102 0 : final snackBar = SnackBar(
103 0 : content: Text(message),
104 0 : action: SnackBarAction(
105 : label: 'URL 복사',
106 0 : onPressed: () => copyUrlToClipboard(context, url),
107 : ),
108 : duration: const Duration(seconds: 4),
109 : );
110 :
111 0 : ScaffoldMessenger.of(context).showSnackBar(snackBar);
112 : } catch (e) {
113 0 : debugPrint('스낵바 표시 오류: $e');
114 : }
115 : }
116 : });
117 : }
118 : }
119 : }
|