Skip to content
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5172f8e
build: измена конфигурация ios проекта в связи с изменением аккаунта …
neekeetuh May 29, 2025
4584621
feat: добавлена тестовая версия логики покупки про версии через аппстор
neekeetuh May 29, 2025
12f85bb
fix: удаление возможности пользователя со статусом про попадать на эк…
neekeetuh May 29, 2025
0c4e4d4
refactor: вынесение констант
neekeetuh May 29, 2025
384b694
fix: вынесение цены про версии в локализацию + исправление ошибок лок…
neekeetuh May 30, 2025
ad3d1f5
refactor: удаление ненужного метода в инициализации провайдера про ве…
neekeetuh May 30, 2025
c324429
style: добавление параметра для использования non-nullable локализации
neekeetuh Jun 1, 2025
92475a8
style: вынесение переменной с апи ключом в класс, где она используется
neekeetuh Jun 1, 2025
e8d8362
refactor: вынесение ассетов в отдельные классы
neekeetuh Jun 1, 2025
fc0cb7b
fix: вынесение добавления listener'a на обновление пользовательской и…
neekeetuh Jun 1, 2025
4218d04
fix: улучшение читабельности методов + добавление обработки ошибки по…
neekeetuh Jun 1, 2025
ac28497
feat: добавление обработки ошибки покупки товара на ui
neekeetuh Jun 1, 2025
baad32b
fix: удаление лишнего consumer'а
neekeetuh Jun 1, 2025
5a94522
fix: изменение логики взаимодействия модулей
neekeetuh Jun 2, 2025
26e1f19
fix: изменение способа инъекции зависимостей для репозитория
neekeetuh Jun 2, 2025
6c882f7
fix: отказ от реактивного спобоса обновления статуса пользователя в п…
neekeetuh Jun 2, 2025
30ba166
Merge branch 'develop' of https://github.com/Student-Labs-2024/aurora…
neekeetuh Jun 2, 2025
30bd629
fix: удаление константных строк, которые должны использоваться через …
neekeetuh Jun 3, 2025
502be15
fix: исправление ошибки, при которой в локальную бд записывались лока…
neekeetuh Jun 5, 2025
9e52e4e
feat + refactor: добавление возможности восстановления покупок пользо…
neekeetuh Jun 8, 2025
c468439
refactor: вынесение данных, хранящихся в провайдере в классы состояни…
neekeetuh Jun 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions frontend/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
PODS:
- Flutter (1.0.0)
- purchases_flutter (5.8.2):
- Flutter
- PurchasesHybridCommon (= 6.3.2)
- PurchasesHybridCommon (6.3.2):
- RevenueCat (= 4.26.1)
- RevenueCat (4.26.1)
- sqflite (0.0.3):
- Flutter
- FlutterMacOS

DEPENDENCIES:
- Flutter (from `Flutter`)
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)

SPEC REPOS:
trunk:
- PurchasesHybridCommon
- RevenueCat

EXTERNAL SOURCES:
Flutter:
:path: Flutter
purchases_flutter:
:path: ".symlinks/plugins/purchases_flutter/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"

SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
purchases_flutter: 32697fa7b2aceb2af2dde25826c5f8b74021fcd1
PurchasesHybridCommon: 98af59169dd9c418eac0725c43f02db92a643b79
RevenueCat: 4e8899a69fd57180ef166237d1eb670023be05de
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec

PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
Expand Down
18 changes: 9 additions & 9 deletions frontend/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = JVX7U43WRX;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = HC3NQ49D3T;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ChessKnock;
Expand All @@ -484,7 +484,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = band.effective.chessknock;
PRODUCT_BUNDLE_IDENTIFIER = dev.effective.chessknock;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
Expand Down Expand Up @@ -664,8 +664,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = JVX7U43WRX;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = HC3NQ49D3T;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ChessKnock;
Expand All @@ -675,7 +675,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = band.effective.chessknock;
PRODUCT_BUNDLE_IDENTIFIER = dev.effective.chessknock;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
Expand All @@ -695,8 +695,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = JVX7U43WRX;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = HC3NQ49D3T;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ChessKnock;
Expand All @@ -706,7 +706,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = band.effective.chessknock;
PRODUCT_BUNDLE_IDENTIFIER = dev.effective.chessknock;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
Expand Down
4 changes: 2 additions & 2 deletions frontend/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
Expand All @@ -38,7 +40,5 @@
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
</dict>
</plist>
1 change: 1 addition & 0 deletions frontend/l10n.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
arb-dir: lib/l10n
template-arb-file: en.arb
output-localization-file: app_localizations.dart
nullable-getter: false
28 changes: 28 additions & 0 deletions frontend/lib/constants/assets.dart
Comment thread
Nailloon marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
sealed class Assets {
static const handbook = "assets/images/icons/handbook.svg";
static const loading = "assets/images/icons/loading.svg";
static const board = "assets/images/board.svg";
static const advantage = 'assets/images/icons/advantage.svg';
static const backArrowIcon = "assets/images/icons/back_arrow_icon.svg";
static const pointLight = "assets/images/icons/point_light.svg";
static const darkSwitch = "assets/images/icons/dark_switch.svg";
static const lightSwitch = "assets/images/icons/light_switch.svg";
static const proSparkles = 'assets/images/icons/pro_sparkles.svg';
static const sun = 'assets/images/icons/sun.svg';
static const moon = 'assets/images/icons/moon.svg';
static const explosion = 'assets/images/icons/explosion.svg';
static const lamp = 'assets/images/icons/lamp.svg';
static const book = 'assets/images/icons/book.svg';
static const chessPiece = 'assets/images/icons/chess_piece.svg';
static const leftBigArrowIcon = "assets/images/icons/left_big_arrow_icon.svg";
static const rightBigArrowIcon =
"assets/images/icons/right_big_arrow_icon.svg";
static const questionIcon = "assets/images/icons/question_icon.svg";
}

sealed class AssetsPieces {
static const bishop = 'assets/images/pieces/bishop.svg';
static const rook = 'assets/images/pieces/rook.svg';
static const knight = 'assets/images/pieces/knight.svg';
static const queen = 'assets/images/pieces/queen.svg';
}
1 change: 0 additions & 1 deletion frontend/lib/constants/constants.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export "colors.dart";
export "text_styles.dart";
export "string_constants.dart";
export 'gradient_consts.dart';
7 changes: 0 additions & 7 deletions frontend/lib/constants/string_constants.dart

This file was deleted.

7 changes: 7 additions & 0 deletions frontend/lib/data_sources/in_app_purchase_data_source.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:flutter/material.dart';

abstract interface class IInAppPurchaseDataSource {
Future<bool> buyProduct(String productId);
Future<bool> checkStatus(String productId);
void init(ValueNotifier<bool> notifier);
}
34 changes: 34 additions & 0 deletions frontend/lib/data_sources/revenuecat_data_source.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
import 'package:frontend/data_sources/in_app_purchase_data_source.dart';
import 'package:purchases_flutter/purchases_flutter.dart';

class RevenueCatDataSource implements IInAppPurchaseDataSource {
//The key of a product should be the same as an entitlement name attached to it
static const _proVersionKey = 'chessknock_pro_version';
@override
Future<bool> buyProduct(String productId) async {
final product = (await Purchases.getProducts([productId])).first;
final customerInfo = await Purchases.purchaseStoreProduct(product);
final isPro = customerInfo.entitlements.active[productId] != null;
return isPro;
}

@override
Future<bool> checkStatus(String productId) async {
final customerInfo = await Purchases.getCustomerInfo();
return customerInfo.entitlements.active.containsKey(productId);
}

@override
void init(ValueNotifier<bool> notifier) {
try {
Purchases.addCustomerInfoUpdateListener((info) {
info.entitlements.active.containsKey(_proVersionKey)
? notifier.value = true
: notifier.value = false;
});
} catch (e) {
throw Exception('function type should be void Function(bool)');
Comment thread
Nailloon marked this conversation as resolved.
Outdated
}
}
}
Comment thread
neekeetuh marked this conversation as resolved.
6 changes: 4 additions & 2 deletions frontend/lib/l10n/en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,7 @@
"moveBackModal": "Ability to return\nthe game board one move back",
"threatsModal": "Display of danger\nof your piece being captured",
"hintsModal": "Display of hints\nfor possible moves",
"description": "Description"
}
"description": "Description",
"price": "1.99 $",
"purchaseError": "Could not buy the product. Try again later"
}
Comment thread
Nailloon marked this conversation as resolved.
6 changes: 4 additions & 2 deletions frontend/lib/l10n/ru.arb
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,7 @@
"moveBackModal": "Возможность вернуть\nигровое поле на ход назад",
"threatsModal": "Отображение опасности\nвзятия вашей фигуры",
"hintsModal": "Отображение подсказок\nвозможных ходов",
"description": "Описание"
}
"description": "Описание",
"price": "199 ₽",
"purchaseError": "Ошибка покупки товара. Попробуйте позже"
}
Comment thread
Nailloon marked this conversation as resolved.
26 changes: 24 additions & 2 deletions frontend/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import "dart:io";

import "package:frontend/data_sources/revenuecat_data_source.dart";
import "package:frontend/exports.dart";
import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "package:frontend/repositories/in_app_purchase_repository.dart";
import "package:provider/provider.dart";
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import "package:purchases_flutter/purchases_flutter.dart";

void main() {
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isIOS) {
await configureRevenueCat();
}
runApp(const MyApp());
}

const _revenueCatApiKey = 'appl_XXuSbFegqvobEdAwmWZnhIlglOX';

Future<void> configureRevenueCat() async {
Purchases.setLogLevel(LogLevel.debug);
Purchases.configure(PurchasesConfiguration(_revenueCatApiKey));
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

Expand All @@ -23,7 +39,13 @@ class MyApp extends StatelessWidget {
create: (context) => ThemeProvider(),
),
ChangeNotifierProvider(
create: (context) => ProVersionProvider(),
create: (context) => ProVersionProvider(
repository: InAppPurchaseRepository(
//TODO: choose data source based off of a platform
dataSource: RevenueCatDataSource(),
proStatusNotifier: ValueNotifier<bool>(false),
),
),
)
],
child: Builder(builder: (context) {
Expand Down
35 changes: 33 additions & 2 deletions frontend/lib/providers/pro_version_provider.dart
Comment thread
neekeetuh marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
import 'package:flutter/material.dart';
import 'package:frontend/repositories/in_app_purchase_repository.dart';

class ProVersionProvider extends ChangeNotifier {
//The key of a product should be the same as an entitlement name attached to it
static const _proVersionKey = 'chessknock_pro_version';

bool _isProStatus = false;
bool _isPurchaseError = false;

final InAppPurchaseRepository _repository;

ProVersionProvider({required InAppPurchaseRepository repository})
: _repository = repository {
_init();
}

void _init() async {
_setProStatus(_repository.getStatus());
}

void _setProStatus(bool status) {
_isProStatus = status;
notifyListeners();
}

void upgradeToPro() {
_setProStatus(true);
void _setPurchaseError(bool isError) {
_isPurchaseError = isError;
notifyListeners();
}

Future<void> upgradeToPro() async {
try {
await _repository.buyProduct(_proVersionKey);
final isPro = _repository.getStatus();
_setProStatus(isPro);
_setPurchaseError(false);
} catch (_) {
_setPurchaseError(true);
await Future.delayed(const Duration(milliseconds: 100));
_setPurchaseError(false);
}
}

void downgradeFromPro() {
_setProStatus(false);
}

bool get isPro => _isProStatus;
bool get isPurchaseError => _isPurchaseError;
}
31 changes: 31 additions & 0 deletions frontend/lib/repositories/in_app_purchase_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:frontend/data_sources/in_app_purchase_data_source.dart';

class InAppPurchaseRepository {
final IInAppPurchaseDataSource _dataSource;
final ValueNotifier<bool> _proStatusNotifier;

InAppPurchaseRepository(
{required IInAppPurchaseDataSource dataSource,
required ValueNotifier<bool> proStatusNotifier})
: _dataSource = dataSource,
_proStatusNotifier = proStatusNotifier {
_init();
}

Future<bool> buyProduct(String productId) {
return _dataSource.buyProduct(productId);
}

Future<bool> checkStatus(String productId) {
return _dataSource.checkStatus(productId);
}

void _init() {
_dataSource.init(_proStatusNotifier);
}

bool getStatus() {
Comment thread
Nailloon marked this conversation as resolved.
Outdated
return _proStatusNotifier.value;
}
}
3 changes: 2 additions & 1 deletion frontend/lib/views/components/button_to_guide.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "package:flutter/material.dart";
import "package:flutter_svg/svg.dart";
import "package:frontend/constants/assets.dart";

class ButtonToGuide extends StatelessWidget {
const ButtonToGuide(
Expand Down Expand Up @@ -29,7 +30,7 @@ class ButtonToGuide extends StatelessWidget {
constraints: const BoxConstraints(),
color: backGroundColor,
icon: SvgPicture.asset(
"assets/images/icons/handbook.svg",
Assets.handbook,
),
),
);
Expand Down
3 changes: 2 additions & 1 deletion frontend/lib/views/components/loading_widget.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "package:flutter/material.dart";
import "package:flutter_svg/flutter_svg.dart";
import "package:frontend/constants/assets.dart";
import "package:frontend/exports.dart";

class LoadingWidget extends StatelessWidget {
Expand All @@ -16,7 +17,7 @@ class LoadingWidget extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
"assets/images/icons/loading.svg",
Assets.loading,
colorFilter: ColorFilter.mode(scheme.primary, BlendMode.srcIn),
),
const SizedBox(
Expand Down
Loading