diff --git a/.github/workflows/flutter.yaml b/.github/workflows/flutter.yaml index f403cf8a..4f284a36 100644 --- a/.github/workflows/flutter.yaml +++ b/.github/workflows/flutter.yaml @@ -11,7 +11,7 @@ on: - main env: JAVA_VERSION: "12.x" - FLUTTER_VERSION: "3.7" + FLUTTER_VERSION: "3.13.3" jobs: analyze: name: Analyze Flutter 🔍 @@ -32,7 +32,7 @@ jobs: uses: subosito/flutter-action@v2 with: channel: "stable" - flutter-version: "3.7" + flutter-version: "3.13.3" - name: Analyze run: | cd my_solved diff --git a/my_solved/android/app/src/main/AndroidManifest.xml b/my_solved/android/app/src/main/AndroidManifest.xml index 46445194..6d34f6ca 100644 --- a/my_solved/android/app/src/main/AndroidManifest.xml +++ b/my_solved/android/app/src/main/AndroidManifest.xml @@ -6,12 +6,14 @@ + + - + - diff --git a/my_solved/android/build.gradle b/my_solved/android/build.gradle index d56cf502..1f8f469f 100644 --- a/my_solved/android/build.gradle +++ b/my_solved/android/build.gradle @@ -27,6 +27,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/my_solved/ios/Podfile.lock b/my_solved/ios/Podfile.lock index 2efc7726..818e4e23 100644 --- a/my_solved/ios/Podfile.lock +++ b/my_solved/ios/Podfile.lock @@ -25,8 +25,8 @@ DEPENDENCIES: - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_native_timezone (from `.symlinks/plugins/flutter_native_timezone/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) - - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: @@ -45,9 +45,9 @@ EXTERNAL SOURCES: fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/ios" + :path: ".symlinks/plugins/path_provider_foundation/darwin" shared_preferences_foundation: - :path: ".symlinks/plugins/shared_preferences_foundation/ios" + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" @@ -56,12 +56,12 @@ SPEC CHECKSUMS: flutter_app_badger: b87fc231847b03b92ce1412aa351842e7e97932f flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 flutter_native_timezone: 5f05b2de06c9776b4cc70e1839f03de178394d22 - fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 - path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 - shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca + fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 - url_launcher_ios: fb12c43172927bb5cf75aeebd073f883801f1993 + url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.1 diff --git a/my_solved/ios/Runner.xcodeproj/project.pbxproj b/my_solved/ios/Runner.xcodeproj/project.pbxproj index 4ba2a0ea..efd1c40b 100644 --- a/my_solved/ios/Runner.xcodeproj/project.pbxproj +++ b/my_solved/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -157,7 +157,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -201,10 +201,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -237,6 +239,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); diff --git a/my_solved/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/my_solved/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a3..a6b826db 100644 --- a/my_solved/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/my_solved/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ get tier => { + 0: Color(0xff2d2d2d), + 1: Color(0xff9d4900), + 2: Color(0xffa54f00), + 3: Color(0xffad5600), + 4: Color(0xffb55d0a), + 5: Color(0xffc67739), + 6: Color(0xff38546e), + 7: Color(0xff3d5a74), + 8: Color(0xff435f7a), + 9: Color(0xff496580), + 10: Color(0xff4e6a86), + 11: Color(0xffd28500), + 12: Color(0xffdf8f00), + 13: Color(0xffec9a00), + 14: Color(0xfff9a518), + 15: Color(0xffffb028), + 16: Color(0xff00c78b), + 17: Color(0xff00d497), + 18: Color(0xff27e2a4), + 19: Color(0xff3ef0b1), + 20: Color(0xff51fdbd), + 21: Color(0xff009ee5), + 22: Color(0xff00a9f0), + 23: Color(0xff00b4fc), + 24: Color(0xff2bbfff), + 25: Color(0xff41caff), + 26: Color(0xffe0004c), + 27: Color(0xffea0053), + 28: Color(0xfff5005a), + 29: Color(0xffff0062), + 30: Color(0xffff3071), + }; } diff --git a/my_solved/lib/models/contest.dart b/my_solved/lib/models/contest.dart index 24ef4f96..86be2ba9 100644 --- a/my_solved/lib/models/contest.dart +++ b/my_solved/lib/models/contest.dart @@ -1,7 +1,7 @@ import 'package:html/dom.dart'; class Contest { - final String venue; + final String? venue; final String name; final String? url; final DateTime startTime; diff --git a/my_solved/lib/models/streak_date.dart b/my_solved/lib/models/streak_date.dart index 077d5181..0cd674a5 100644 --- a/my_solved/lib/models/streak_date.dart +++ b/my_solved/lib/models/streak_date.dart @@ -4,6 +4,7 @@ class StreakDate { final int year; final int weekDay; final int solvedCount; + final bool isSolved; final bool isFuture; final bool isFrozen; final bool isRepaired; @@ -14,6 +15,7 @@ class StreakDate { required this.year, required this.weekDay, required this.solvedCount, + required this.isSolved, required this.isFuture, required this.isFrozen, required this.isRepaired}); diff --git a/my_solved/lib/models/user/grass.dart b/my_solved/lib/models/user/grass.dart index 2f18c363..86076b68 100644 --- a/my_solved/lib/models/user/grass.dart +++ b/my_solved/lib/models/user/grass.dart @@ -3,12 +3,14 @@ class Grass { final dynamic theme; final int currentStreak; final int longestStreak; + final String topic; const Grass({ required this.grass, required this.theme, required this.currentStreak, required this.longestStreak, + required this.topic, }); factory Grass.fromJson(Map json) { @@ -17,6 +19,7 @@ class Grass { theme: json['theme'], currentStreak: json['currentStreak'], longestStreak: json['longestStreak'], + topic: json['topic'], ); } } diff --git a/my_solved/lib/services/network_service.dart b/my_solved/lib/services/network_service.dart index 8ad49dba..1de26f18 100644 --- a/my_solved/lib/services/network_service.dart +++ b/my_solved/lib/services/network_service.dart @@ -96,7 +96,7 @@ class NetworkService { Future requestStreak(String handle) async { final response = await http.get(Uri.parse( - "https://solved.ac/api/v3/user/grass?handle=$handle&topic=today-solved")); + "https://solved.ac/api/v3/user/grass?handle=$handle&topic=default")); final statusCode = response.statusCode; if (statusCode == 200) { @@ -127,7 +127,7 @@ class NetworkService { if (statusCode == 200) { List tagRatings = - json.decode(response.body).map((json) { + json.decode(response.body).map((json) { return TagRatings.fromJson(json); }).toList(); return tagRatings; @@ -144,7 +144,7 @@ class NetworkService { if (statusCode == 200) { SearchSuggestion search = - SearchSuggestion.fromJson(jsonDecode(response.body)); + SearchSuggestion.fromJson(jsonDecode(response.body)); return search; } else { throw Exception('Fail to load'); @@ -152,8 +152,8 @@ class NetworkService { } // 문제 검색 - Future requestSearchProblem( - String query, int? page, String? sort, String? direction) async { + Future requestSearchProblem(String query, int? page, + String? sort, String? direction) async { String url = "https://solved.ac/api/v3/search/problem?query=$query"; if (page != null) { url += "&page=$page"; @@ -214,7 +214,9 @@ class NetworkService { Future>> requestContests() async { List upcomingContests(dom.Element element) { - if (element.getElementsByClassName('col-md-12').length < 5) { + if (element + .getElementsByClassName('col-md-12') + .length < 5) { return element .getElementsByClassName('col-md-12')[2] .getElementsByTagName('tbody') @@ -238,7 +240,11 @@ class NetworkService { } List ongoingContests(dom.Element element) { - if (element.getElementsByClassName('col-md-12').length < 5) { + if (element + .getElementsByClassName('col-md-12') + .length < 5) { + return []; + } else { return element .getElementsByClassName('col-md-12')[2] .getElementsByTagName('tbody') @@ -248,8 +254,6 @@ class NetworkService { .map((e) { return Contest.fromElement(e); }).toList(); - } else { - return []; } } @@ -273,7 +277,9 @@ class NetworkService { .replaceAll('일', '') .split(' '); DateTime startTime = DateTime.parse( - "${startTimeList[0].padLeft(4, "0")}-${startTimeList[1].padLeft(2, "0")}-${startTimeList[2].padLeft(2, "0")}T${startTimeList[3].padLeft(2, "0")}:00+09:00") + "${startTimeList[0].padLeft(4, "0")}-${startTimeList[1].padLeft( + 2, "0")}-${startTimeList[2].padLeft(2, "0")}T${startTimeList[3] + .padLeft(2, "0")}:00+09:00") .toLocal(); List endTimeList = element .getElementsByTagName('td')[4] @@ -284,14 +290,17 @@ class NetworkService { .replaceAll('일', '') .split(' '); DateTime endTime = DateTime.parse( - "${endTimeList[0].padLeft(4, "0")}-${endTimeList[1].padLeft(2, "0")}-${endTimeList[2].padLeft(2, "0")}T${endTimeList[3].padLeft(2, "0")}:00+09:00") + "${endTimeList[0].padLeft(4, "0")}-${endTimeList[1].padLeft( + 2, "0")}-${endTimeList[2].padLeft(2, "0")}T${endTimeList[3] + .padLeft(2, "0")}:00+09:00") .toLocal(); return Contest( venue: 'BOJ Open', name: e.getElementsByTagName('td')[0].text.trim(), url: - 'https://www.acmicpc.net${e.getElementsByTagName('td')[0].getElementsByTagName('a')[0].attributes['href']}', + 'https://www.acmicpc.net${e.getElementsByTagName('td')[0] + .getElementsByTagName('a')[0].attributes['href']}', startTime: startTime, endTime: endTime, ); @@ -299,12 +308,18 @@ class NetworkService { } final others = - await http.get(Uri.parse("https://www.acmicpc.net/contest/other/list")); + await http.get(Uri.parse("https://www.acmicpc.net/contest/other/list")); dom.Document docOthers = parser.parse(others.body); + final othersStatus = others.statusCode; final ended = await http .get(Uri.parse("https://www.acmicpc.net/contest/official/list")); dom.Document docEnded = parser.parse(ended.body); + final endedStatus = ended.statusCode; + + if (othersStatus != 200 || endedStatus != 200) { + throw Exception('Failed to load'); + } return [ ongoingContests(docOthers.body!), @@ -315,7 +330,7 @@ class NetworkService { Future> requestArenaContests() async { final response = - await http.get(Uri.parse("https://solved.ac/api/v3/arena/contests")); + await http.get(Uri.parse("https://solved.ac/api/v3/arena/contests")); final statusCode = response.statusCode; if (statusCode == 200) { @@ -337,7 +352,7 @@ class NetworkService { Future requestSiteStats() async { final response = - await http.get(Uri.parse("https://solved.ac/api/v3/site/stats")); + await http.get(Uri.parse("https://solved.ac/api/v3/site/stats")); final statusCode = response.statusCode; debugPrint(response.body); diff --git a/my_solved/lib/views/contest_view.dart b/my_solved/lib/views/contest_view.dart index e9fe47aa..e71aec41 100644 --- a/my_solved/lib/views/contest_view.dart +++ b/my_solved/lib/views/contest_view.dart @@ -80,7 +80,8 @@ extension _ContestStateExtension on _ContestViewState { scrollDirection: Axis.horizontal, shrinkWrap: true, itemBuilder: (context, index) { - String venue = snapshot.data?.keys.elementAt(index) ?? ""; + String venue = + snapshot.data?.keys.elementAt(index) ?? "boj open"; bool isSelected = snapshot.data?[venue] ?? true; bool isOthers = venue == 'Others'; @@ -97,19 +98,19 @@ extension _ContestStateExtension on _ContestViewState { alignment: Alignment.center, child: Row( children: [ - // isOthers - // ? Icon( - // Icons.more_horiz, - // size: 14, - // color: isSelected - // ? Colors.grey[200] - // : Colors.grey[400], - // ) - // : ExtendedImage.asset( - // 'lib/assets/venues/${venue.toLowerCase()}.png', - // fit: BoxFit.fill, - // width: 14, - // ), + isOthers + ? Icon( + Icons.more_horiz, + size: 14, + color: isSelected + ? Colors.grey[200] + : Colors.grey[400], + ) + : ExtendedImage.asset( + 'lib/assets/venues/${venue.toLowerCase()}.png', + fit: BoxFit.fill, + width: 14, + ), SizedBox( width: 5, ), @@ -173,7 +174,7 @@ extension _ContestStateExtension on _ContestViewState { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - for (var c in contests) contest(context, c), + for (var c in contests) contest(context, c, index), ], )); } else { @@ -184,7 +185,7 @@ extension _ContestStateExtension on _ContestViewState { } /// 대회 위젯 - Widget contest(BuildContext context, Contest contest) { + Widget contest(BuildContext context, Contest contest, int contestType) { bool hasUrl = contest.url != null; bool isArena = false; if (contest.venue == 'BOJ Open') { @@ -195,13 +196,14 @@ extension _ContestStateExtension on _ContestViewState { /// 대회 위젯 상단 /// 플랫폼 아이콘, 대회 이름, 대회 일정 Widget contestTop(Contest contest) { + String venue = contest.venue?.toLowerCase() ?? "boj open"; return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // ExtendedImage.asset( - // 'lib/assets/venues/${contest.venue.toLowerCase()}.png', - // width: 30, - // ), + ExtendedImage.asset( + 'lib/assets/venues/$venue.png', + width: 30, + ), SizedBox(width: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -250,50 +252,51 @@ extension _ContestStateExtension on _ContestViewState { }, ), SizedBox(width: 10), - FutureBuilder( - future: notificationService.getContestPush(contest.name), - builder: (context, snapshot) { - bool isPush = snapshot.data ?? false; - return TextButton( - style: ButtonStyle( - shape: MaterialStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10))), - minimumSize: MaterialStateProperty.all(Size(0, 0)), - backgroundColor: MaterialStateProperty.all(isPush - ? CupertinoTheme.of(context).main - : Colors.black12), - padding: MaterialStateProperty.all( - EdgeInsets.symmetric(horizontal: 10, vertical: 5)), - ), - child: Text(isPush ? '알림 설정 완료' : '알림 설정하기', - style: TextStyle( - color: isPush ? Colors.white : Colors.grey, - fontSize: 12, - )), - onPressed: () { - // ignore: invalid_use_of_protected_member - setState(() { - notificationService.toggleContestPush(contest); - }); - Fluttertoast.showToast( - msg: isPush ? '알림이 해제되었습니다.' : '알림이 설정되었습니다.', - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.grey[700], - textColor: Colors.white, - fontSize: 14.0, - ); - }, - ); - }, - ), + if (contestType == 1) + FutureBuilder( + future: notificationService.getContestPush(contest.name), + builder: (context, snapshot) { + bool isPush = snapshot.data ?? false; + return TextButton( + style: ButtonStyle( + shape: MaterialStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10))), + minimumSize: MaterialStateProperty.all(Size(0, 0)), + backgroundColor: MaterialStateProperty.all(isPush + ? CupertinoTheme.of(context).main + : Colors.black12), + padding: MaterialStateProperty.all( + EdgeInsets.symmetric(horizontal: 10, vertical: 5)), + ), + child: Text(isPush ? '알림 설정 완료' : '알림 설정하기', + style: TextStyle( + color: isPush ? Colors.white : Colors.grey, + fontSize: 12, + )), + onPressed: () { + // ignore: invalid_use_of_protected_member + setState(() { + notificationService.toggleContestPush(contest); + }); + Fluttertoast.showToast( + msg: isPush ? '알림이 해제되었습니다.' : '알림이 설정되었습니다.', + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.grey[700], + textColor: Colors.white, + fontSize: 14.0, + ); + }, + ); + }, + ), Spacer(), - // isArena - // ? ExtendedImage.asset( - // 'lib/assets/venues/ac arena.png', - // height: 20, - // ) - // : SizedBox.shrink() + isArena + ? ExtendedImage.asset( + 'lib/assets/venues/ac arena.png', + height: 20, + ) + : SizedBox.shrink() ], ); } diff --git a/my_solved/lib/widgets/user_widget.dart b/my_solved/lib/widgets/user_widget.dart index 5fee86ba..3a130b2e 100644 --- a/my_solved/lib/widgets/user_widget.dart +++ b/my_solved/lib/widgets/user_widget.dart @@ -126,6 +126,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, int currentStreak = snapshot.data!.currentStreak; int longestStreak = snapshot.data!.longestStreak; String theme = snapshot.data!.theme ?? 'default'; + String topic = snapshot.data!.topic; bool solvedToday = false; @@ -138,7 +139,8 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, month: now.month, day: now.day, weekDay: now.weekday, - solvedCount: 0, + solvedCount: -1, + isSolved: false, isFuture: false, isFrozen: false, isRepaired: false); @@ -153,6 +155,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, day: now.day, weekDay: now.weekday, solvedCount: grass.last['value'], + isSolved: grass.last['value'] >= 0, isFuture: false, isFrozen: false, isRepaired: false); @@ -177,6 +180,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, day: day, weekDay: weekDay, solvedCount: 0, + isSolved: false, isFuture: true, isFrozen: false, isRepaired: false)); @@ -192,7 +196,8 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, int month = yesterday.month; int day = yesterday.day; int weekDay = yesterday.weekday; - int solvedCount = 0; + int solvedCount = -1; + bool isSolved = false; bool isFrozen = false; bool isRepaired = false; String gl = ''; @@ -207,6 +212,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, isRepaired = true; } else { solvedCount = grass.last['value']; + isSolved = solvedCount >= 0; maxSolvedCount = max(maxSolvedCount, solvedCount); } grass.removeLast(); @@ -218,6 +224,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, day: day, weekDay: weekDay, solvedCount: solvedCount, + isSolved: isSolved, isFuture: false, isFrozen: isFrozen, isRepaired: isRepaired)); @@ -275,9 +282,11 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, child: SvgPicture.asset( 'lib/assets/icons/streak.svg', width: 20, - color: solvedToday - ? CupertinoTheme.of(context).main - : Color(0xff8a8f95), + colorFilter: ColorFilter.mode( + solvedToday + ? CupertinoTheme.of(context).main + : Color(0xff8a8f95), + BlendMode.srcATop), ), ), const SizedBox(width: 10), @@ -322,6 +331,39 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, itemCount: 35, itemBuilder: (context, index) { var date = streakDates[index]; + + Color color = Color(0xffdddfe0); + if (date.isRepaired) { + color = CupertinoTheme.of(context).tier[0]!; + } else if (date.isSolved) { + if (topic == 'today-solved-max-tier') { + color = CupertinoTheme.of(context) + .tier[date.solvedCount]!; + } else if (topic == 'today-solved') { + color = CupertinoTheme.of(context).streakTheme[ + theme]![themeAccent(date.solvedCount)]; + } + } + + String textTooltipBottom = ''; + if (date.isFrozen) { + textTooltipBottom = '스트릭 프리즈 사용'; + } else if (date.isRepaired) { + textTooltipBottom = '스트릭 리페어 사용'; + } else if (!date.isSolved) { + textTooltipBottom = '-'; + } else { + if (topic == 'today-solved-max-tier') { + if (date.solvedCount == 0) { + textTooltipBottom = 'Unrated'; + } else { + textTooltipBottom = tierStr(date.solvedCount); + } + } else if (topic == 'today-solved') { + textTooltipBottom = '${date.solvedCount}문제 해결'; + } + } + try { return date.isFuture ? SizedBox.shrink() @@ -336,11 +378,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, '${date.year}/${date.month}/${date.day}\n', ), TextSpan( - text: date.isFrozen - ? '스트릭 프리즈 사용' - : date.isRepaired - ? '스트릭 리페어 사용' - : '${date.solvedCount}문제 해결', + text: textTooltipBottom, ), ]), triggerMode: TooltipTriggerMode.tap, @@ -356,13 +394,7 @@ Widget grass(BuildContext context, AsyncSnapshot userSnapshot, margin: EdgeInsets.all(5), alignment: Alignment.center, decoration: BoxDecoration( - color: date.isRepaired - ? CupertinoTheme.of(context) - .streakTheme[theme]![0] - : CupertinoTheme.of(context) - .streakTheme[theme]![ - themeAccent( - date.solvedCount)], + color: color, borderRadius: BorderRadius.circular(5), ), @@ -412,74 +444,6 @@ Widget top100( int tier = snapshot.data?.tier ?? 0; int rank = snapshot.data?.rank ?? 0; - String tierStr(int tier) { - if (tier == 1) { - return 'Bronze V'; - } else if (tier == 2) { - return 'Bronze IV'; - } else if (tier == 3) { - return 'Bronze III'; - } else if (tier == 4) { - return 'Bronze II'; - } else if (tier == 5) { - return 'Bronze I'; - } else if (tier == 6) { - return 'Silver V'; - } else if (tier == 7) { - return 'Silver IV'; - } else if (tier == 8) { - return 'Silver III'; - } else if (tier == 9) { - return 'Silver II'; - } else if (tier == 10) { - return 'Silver I'; - } else if (tier == 11) { - return 'Gold V'; - } else if (tier == 12) { - return 'Gold IV'; - } else if (tier == 13) { - return 'Gold III'; - } else if (tier == 14) { - return 'Gold II'; - } else if (tier == 15) { - return 'Gold I'; - } else if (tier == 16) { - return 'Platinum V'; - } else if (tier == 17) { - return 'Platinum IV'; - } else if (tier == 18) { - return 'Platinum III'; - } else if (tier == 19) { - return 'Platinum II'; - } else if (tier == 20) { - return 'Platinum I'; - } else if (tier == 21) { - return 'Diamond V'; - } else if (tier == 22) { - return 'Diamond IV'; - } else if (tier == 23) { - return 'Diamond III'; - } else if (tier == 24) { - return 'Diamond II'; - } else if (tier == 25) { - return 'Diamond I'; - } else if (tier == 26) { - return 'Ruby V'; - } else if (tier == 27) { - return 'Ruby IV'; - } else if (tier == 28) { - return 'Ruby III'; - } else if (tier == 29) { - return 'Ruby II'; - } else if (tier == 30) { - return 'Ruby I'; - } else if (tier == 31) { - return 'Master'; - } else { - return 'Unrated'; - } - } - Widget top100Header(int rating, int tier, int rank, BuildContext context) { Color rankBoxColor(int rankNum) { if (rankNum == 1) { @@ -972,7 +936,9 @@ Widget badges(BuildContext context, Future future) { SvgPicture.asset( 'lib/assets/icons/badge.svg', width: MediaQuery.of(context).size.width * 0.04, - color: Colors.black45, + colorFilter: ColorFilter.mode( + CupertinoTheme.of(context).textTheme.textStyle.color!, + BlendMode.srcATop), ), const SizedBox(width: 5), Text( @@ -1460,6 +1426,74 @@ Widget badge(BuildContext context, Future future) { }); } +String tierStr(int tier) { + if (tier == 1) { + return 'Bronze V'; + } else if (tier == 2) { + return 'Bronze IV'; + } else if (tier == 3) { + return 'Bronze III'; + } else if (tier == 4) { + return 'Bronze II'; + } else if (tier == 5) { + return 'Bronze I'; + } else if (tier == 6) { + return 'Silver V'; + } else if (tier == 7) { + return 'Silver IV'; + } else if (tier == 8) { + return 'Silver III'; + } else if (tier == 9) { + return 'Silver II'; + } else if (tier == 10) { + return 'Silver I'; + } else if (tier == 11) { + return 'Gold V'; + } else if (tier == 12) { + return 'Gold IV'; + } else if (tier == 13) { + return 'Gold III'; + } else if (tier == 14) { + return 'Gold II'; + } else if (tier == 15) { + return 'Gold I'; + } else if (tier == 16) { + return 'Platinum V'; + } else if (tier == 17) { + return 'Platinum IV'; + } else if (tier == 18) { + return 'Platinum III'; + } else if (tier == 19) { + return 'Platinum II'; + } else if (tier == 20) { + return 'Platinum I'; + } else if (tier == 21) { + return 'Diamond V'; + } else if (tier == 22) { + return 'Diamond IV'; + } else if (tier == 23) { + return 'Diamond III'; + } else if (tier == 24) { + return 'Diamond II'; + } else if (tier == 25) { + return 'Diamond I'; + } else if (tier == 26) { + return 'Ruby V'; + } else if (tier == 27) { + return 'Ruby IV'; + } else if (tier == 28) { + return 'Ruby III'; + } else if (tier == 29) { + return 'Ruby II'; + } else if (tier == 30) { + return 'Ruby I'; + } else if (tier == 31) { + return 'Master'; + } else { + return 'Unrated'; + } +} + Color levelColor(int level) { if (level == 0) { return Color(0xFF2D2D2D); diff --git a/my_solved/macos/Podfile b/my_solved/macos/Podfile index dade8dfa..049abe29 100644 --- a/my_solved/macos/Podfile +++ b/my_solved/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.11' +platform :osx, '10.14' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/my_solved/macos/Runner.xcodeproj/project.pbxproj b/my_solved/macos/Runner.xcodeproj/project.pbxproj index 3198479f..0a8937c0 100644 --- a/my_solved/macos/Runner.xcodeproj/project.pbxproj +++ b/my_solved/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -26,6 +26,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + C1B90827029C91B8C22A570C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD42C41EAACAF26B0896DDEF /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 20870788BB4D30E8F822706C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* my_solved.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "my_solved.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* my_solved.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = my_solved.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,8 +68,11 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 66D8BAC6CB48A4013742C0EA /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + DD42C41EAACAF26B0896DDEF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F71D1730EEA4ED2F4EBDF9B2 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,12 +80,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C1B90827029C91B8C22A570C /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 20F82CF46E7F6443E71946EC /* Pods */ = { + isa = PBXGroup; + children = ( + F71D1730EEA4ED2F4EBDF9B2 /* Pods-Runner.debug.xcconfig */, + 66D8BAC6CB48A4013742C0EA /* Pods-Runner.release.xcconfig */, + 20870788BB4D30E8F822706C /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -99,6 +116,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 20F82CF46E7F6443E71946EC /* Pods */, ); sourceTree = ""; }; @@ -148,6 +166,7 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + DD42C41EAACAF26B0896DDEF /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 66C16FA5AAA3B3A9BFD37575 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + A2B94C6524C2BDEA45F10215 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -182,7 +203,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -235,6 +256,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -270,6 +292,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 66C16FA5AAA3B3A9BFD37575 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + A2B94C6524C2BDEA45F10215 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -344,7 +405,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -423,7 +484,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -470,7 +531,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/my_solved/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/my_solved/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 82f37c0e..3637041b 100644 --- a/my_solved/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/my_solved/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/my_solved/pubspec.yaml b/my_solved/pubspec.yaml index f9747e10..6a2ff1a6 100644 --- a/my_solved/pubspec.yaml +++ b/my_solved/pubspec.yaml @@ -3,7 +3,7 @@ description: For solving problems in the world of programming; base on solved.ac publish_to: "none" # Remove this line if you wish to publish to pub.dev -version: 1.1.5+56 +version: 1.1.5+58 environment: sdk: ">=2.18.2 <3.0.0" @@ -14,7 +14,7 @@ dependencies: http: ^1.1.0 provider: ^6.0.5 html: ^0.15.2 - flutter_svg: ^1.1.6 + flutter_svg: ^2.0.7 cupertino_icons: ^1.0.5 extended_image: ^8.1.0 shared_preferences: ^2.0.18