Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warframe Market partial intergration #101

Merged
merged 60 commits into from
Jul 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
aaad6f8
fix(darvo): show an error icon when an item hasn't been found
SlayerOrnstein Jul 12, 2021
c7e0c3a
chore: update fastlane
SlayerOrnstein Jul 13, 2021
c9f9330
chore(release): 2.3.20
semantic-release-bot Jul 13, 2021
8a65c4a
Merge branch 'master' into navis_market
SlayerOrnstein Jul 13, 2021
edcfc21
fix: remove empty values for new weapons
SlayerOrnstein Jul 15, 2021
8092f98
chore: add market widget and logic
SlayerOrnstein Jul 15, 2021
152940d
chore: update android build tools to 4.2.2
SlayerOrnstein Jul 15, 2021
1621ddd
chore: remove forced light theme mode
SlayerOrnstein Jul 15, 2021
bd8dafa
chore: made offline grey color lighter to contrast properly in dark mode
SlayerOrnstein Jul 15, 2021
f4f584c
chore: replace the word "Price" for "Platinum" to avoid confusion
SlayerOrnstein Jul 15, 2021
0383e13
fix: back key opens drawer now works properly
SlayerOrnstein Jul 15, 2021
4259908
chore: remove green border when debugging
SlayerOrnstein Jul 15, 2021
67c9ee9
style: remove unsused imports
SlayerOrnstein Jul 15, 2021
e34cc9c
chore: codex entry now has a static height
SlayerOrnstein Jul 15, 2021
f892bd0
chore: scale codex image by width not height
SlayerOrnstein Jul 15, 2021
8ce2593
chore: convert MarketCubit into a bloc for hydration
SlayerOrnstein Jul 15, 2021
c1a059c
chore: possible fix for entry info being cut off on some devices
SlayerOrnstein Jul 16, 2021
f429869
chore(ios): update podfile
SlayerOrnstein Jul 16, 2021
55b9a2f
chore: increased height of entry body
SlayerOrnstein Jul 16, 2021
29f21a7
fix: platfrom not saving properly
SlayerOrnstein Jul 16, 2021
09b6608
chore: more flexible way of rendering entry info
SlayerOrnstein Jul 16, 2021
e0ecfa8
perf: improve caching
SlayerOrnstein Jul 16, 2021
0324c3a
style: import cleanup
SlayerOrnstein Jul 16, 2021
d7e7861
test: fix test using hive boxes
SlayerOrnstein Jul 16, 2021
7c7c22d
chore: filter by sell orders only
SlayerOrnstein Jul 16, 2021
28a4a0f
chore(release): 2.3.20
semantic-release-bot Jul 13, 2021
69a6e5b
chore: add market widget and logic
SlayerOrnstein Jul 15, 2021
410b390
chore: update android build tools to 4.2.2
SlayerOrnstein Jul 15, 2021
2e8831d
chore: remove forced light theme mode
SlayerOrnstein Jul 15, 2021
05fbcc0
chore: made offline grey color lighter to contrast properly in dark mode
SlayerOrnstein Jul 15, 2021
1e15b58
chore: replace the word "Price" for "Platinum" to avoid confusion
SlayerOrnstein Jul 15, 2021
2cac8b5
fix: back key opens drawer now works properly
SlayerOrnstein Jul 15, 2021
ca846f8
chore: remove green border when debugging
SlayerOrnstein Jul 15, 2021
30969cc
style: remove unsused imports
SlayerOrnstein Jul 15, 2021
898c64a
chore: codex entry now has a static height
SlayerOrnstein Jul 15, 2021
8d3c6a7
chore: convert MarketCubit into a bloc for hydration
SlayerOrnstein Jul 15, 2021
4831fcd
chore: possible fix for entry info being cut off on some devices
SlayerOrnstein Jul 16, 2021
043cfea
chore: more flexible way of rendering entry info
SlayerOrnstein Jul 16, 2021
014e63f
perf: improve caching
SlayerOrnstein Jul 16, 2021
687b297
style: import cleanup
SlayerOrnstein Jul 16, 2021
b6469c8
test: fix test using hive boxes
SlayerOrnstein Jul 16, 2021
3bdc04b
chore: filter by sell orders only
SlayerOrnstein Jul 16, 2021
f6f4929
Merge branch 'navis_market' of https://github.com/WFCD/navis into nav…
SlayerOrnstein Jul 17, 2021
e376eea
chore: increased the height of the entry header
SlayerOrnstein Jul 17, 2021
ac5c74a
chore: stop Hive from init twice
SlayerOrnstein Jul 17, 2021
0ddc135
chore: flutter pub upgrade
SlayerOrnstein Jul 17, 2021
847823b
chore: allow entry header to color the status bar
SlayerOrnstein Jul 18, 2021
f8d10f7
chore: invalidate cache after 5 mins
SlayerOrnstein Jul 18, 2021
6c2d64a
leverage comparable (#104)
TobiTenno Jul 22, 2021
8aec73c
Merge branch 'master' into navis_market
SlayerOrnstein Jul 22, 2021
ac16921
fix: temporarly disabled guide player
SlayerOrnstein Jul 22, 2021
8dc6777
Merge branch 'master' into navis_market
SlayerOrnstein Jul 30, 2021
dd89708
fix: trader showing arriving when actually leaving and vice versa
SlayerOrnstein Jul 30, 2021
b4e3152
fix: tab entry adding extra space when not needed
SlayerOrnstein Jul 30, 2021
b25b550
fix: centered rank light
SlayerOrnstein Jul 30, 2021
dcc8d51
chore: implemented caching for market's item list
SlayerOrnstein Jul 31, 2021
ca2e3da
chore: display mod name in app bar
SlayerOrnstein Jul 31, 2021
0ce6aa8
chore: better null checking for Item.patchlog
SlayerOrnstein Jul 31, 2021
1d5d44a
chore: update deps
SlayerOrnstein Jul 31, 2021
b5a52ec
Merge branch 'master' into navis_market
SlayerOrnstein Jul 31, 2021
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
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ flutter_*.mp4
*.iws
.idea/

# Gradle
.gradle/
gradle/
gradlew
gradlew.bat
local.properties

# Visual Studio Code related
.vscode/

Expand Down
3 changes: 3 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
include: package:very_good_analysis/analysis_options.yaml

analyzer:
exclude:
- lib/generated/l10n.dart
- lib/generated/intl/messages_*.dart
- lib/src/**/*g.dart
- lib/src/models/**/*.g.dart

linter:
rules:
public_member_api_docs: false
prefer_relative_imports: true
always_use_package_imports: false

2 changes: 2 additions & 0 deletions android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:defaultFocusHighlightEnabled">false</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Expand All @@ -14,5 +15,6 @@
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@android:color/white</item>
<item name="android:defaultFocusHighlightEnabled">false</item>
</style>
</resources>
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildscript {

dependencies {
//noinspection GradleDependency
classpath 'com.android.tools.build:gradle:4.2.1'
classpath 'com.android.tools.build:gradle:4.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.8'
}
Expand Down
9 changes: 1 addition & 8 deletions lib/core/local/user_settings.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import 'dart:developer';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:logging/logging.dart';
import 'package:matomo/matomo.dart';
import 'package:path_provider/path_provider.dart';
import 'package:wfcd_client/wfcd_client.dart';

import '../../constants/storage_keys.dart';
Expand All @@ -17,13 +15,8 @@ class Usersettings {

static Usersettings? _instance;

static Future<Usersettings> initUsersettings([Directory? directory]) async {
static Future<Usersettings> initUsersettings() async {
log('Initializing Usersettings Hive', level: Level.INFO.value);

Hive.init(
directory?.path ?? (await getApplicationDocumentsDirectory()).path,
);

final box = await Hive.openBox<dynamic>('user_settings');

return _instance ??= Usersettings._(box);
Expand Down
72 changes: 72 additions & 0 deletions lib/features/codex/data/datasources/market_cache.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'dart:developer';

import 'package:hive/hive.dart';
import 'package:market_client/market_client.dart';

class MarketCache {
const MarketCache._(this._box);

final Box<dynamic> _box;

static MarketCache? _instance;

static Future<MarketCache> initCache() async {
log('Initializing MarketCache Hive');
final box = await Hive.openBox<dynamic>('market_cache').catchError(
(Object error, StackTrace stack) {
log('Unable to open Hive box', error: error, stackTrace: stack);
},
);

return _instance ??= MarketCache._(box);
}

static const _itemsTimestamp = 'marketItemTimestampe';
static const _marketItems = 'marketItems';
static const _orderTimestamp = 'orderTimestamp';
static const _itemName = 'itemName';
static const _ordersKey = 'marketOrders';

void cacheItems(List<MarketItem> items) {
_box
..put(_itemsTimestamp, DateTime.now())
..put(_marketItems, items.map((e) => e.toJson()).toList());
}

void cacheOrders(String itemName, List<ItemOrder> orders) {
_box
..put(_orderTimestamp, DateTime.now())
..put(_itemName, itemName)
..put(_ordersKey, orders.map((o) => o.toJson()).toList());
}

DateTime? getItemsTimestamp() {
return _box.get(_itemsTimestamp);
}

String? getCachedItemName() {
return _box.get(_itemName);
}

DateTime? getOrderTimestamp() {
return _box.get(_orderTimestamp);
}

List<ItemOrder>? getCachedOrders() {
final cached = _box.get(_ordersKey) as List<Map<String, dynamic>>?;

if (cached != null) {
return cached.map((e) => ItemOrder.fromJson(e)).toList();
}

return null;
}

List<MarketItem>? getCachedItems() {
final cached = _box.get(_marketItems) as List<Map<String, dynamic>>?;

if (cached != null) {
return cached.map((e) => MarketItem.fromJson(e)).toList();
}
}
}
158 changes: 158 additions & 0 deletions lib/features/codex/data/repositories/market_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:market_client/market_client.dart';
import 'package:oxidized/oxidized.dart';
import 'package:wfcd_client/wfcd_client.dart';

import '../../../../core/error/exceptions.dart';
import '../../../../core/error/failures.dart';
import '../../../../core/local/user_settings.dart';
import '../../../../core/network/network_info.dart';
import '../../domian/repositories/market_repository.dart';
import '../datasources/market_cache.dart';

class MarketRepositoryImpl extends MarketRepository {
const MarketRepositoryImpl(this.networkInfo, this.usersettings, this.cache);

final NetworkInfo networkInfo;
final Usersettings usersettings;
final MarketCache cache;

@override
Future<Result<List<ItemOrder>, Failure>> retriveOrders(
String itemName) async {
const _expiredCacheTime = Duration(minutes: 5);
final cTimestamp = cache.getOrderTimestamp()?.difference(DateTime.now());
final cItem = cache.getCachedItemName();

Result<List<ItemOrder>, Failure> getcached() {
final cached = cache.getCachedOrders();

if (cached != null) {
return Ok(cached);
} else {
return Err(CacheFailure());
}
}

if (cItem != itemName &&
(cTimestamp ?? _expiredCacheTime) <= _expiredCacheTime) {
if (await networkInfo.isConnected) {
final items = await getItems();

final req = MarketRequest(
itemUrl: itemName,
languageCode: usersettings.language?.languageCode ?? 'en',
platform: usersettings.platform,
items: items.match((i) => i, (f) => throw CacheException()),
);

try {
final orders = await compute(_retriveOrders, req);

cache.cacheOrders(itemName, orders);
return Ok(orders);
} on SocketException {
return Err(ServerFailure());
}
} else {
return getcached();
}
} else {
return getcached();
}
}

Future<Result<List<MarketItem>, Failure>> getItems() async {
const _expiredCacheTime = Duration(days: 7);
final cTimestamp = cache.getItemsTimestamp();
final cDuration =
cTimestamp?.difference(DateTime.now()) ?? _expiredCacheTime;

Result<List<MarketItem>, Failure> getcached() {
final cached = cache.getCachedItems();

if (cached != null) {
return Ok(cached);
} else {
return Err(CacheFailure());
}
}

if (cDuration >= _expiredCacheTime) {
if (await networkInfo.isConnected) {
final req = MarketRequest(
languageCode: usersettings.language?.languageCode ?? 'en',
platform: usersettings.platform,
);

try {
final items = await compute(_getItems, req);

cache.cacheItems(items);
return Ok(items);
} on SocketException {
return getcached();
}
} else {
return getcached();
}
} else {
return getcached();
}
}

static Future<List<ItemOrder>> _retriveOrders(MarketRequest req) async {
final client = MarketHttpClient(
platform: req.platform.marketPlatform,
language: req.languageCode,
);
final api = MarketClient(client: client);
final itemUrl =
req.items.firstWhere((e) => e.itemName.contains(req.itemUrl!));

return (await api.searchOrders(itemUrl.urlName))
.where((o) => o.orderType == OrderType.sell)
.toList();
}

static Future<List<MarketItem>> _getItems(MarketRequest req) async {
final client = MarketHttpClient(
platform: req.platform.marketPlatform,
language: req.languageCode,
);
final api = MarketClient(client: client);

return await api.getMarketItems();
}
}

class MarketRequest {
const MarketRequest({
this.itemUrl,
required this.languageCode,
required this.platform,
this.items = const <MarketItem>[],
});

final String? itemUrl;
final String languageCode;
final GamePlatforms platform;
final List<MarketItem> items;
}

extension GamePlatformsX on GamePlatforms {
MarketPlatform get marketPlatform {
switch (this) {
case GamePlatforms.pc:
return MarketPlatform.pc;
case GamePlatforms.ps4:
return MarketPlatform.ps4;
case GamePlatforms.xb1:
return MarketPlatform.xbox;
case GamePlatforms.swi:
return MarketPlatform.swi;
}
}
}
10 changes: 10 additions & 0 deletions lib/features/codex/domian/repositories/market_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:market_client/market_client.dart';
import 'package:oxidized/oxidized.dart';

import '../../../../core/error/failures.dart';

abstract class MarketRepository {
const MarketRepository();

Future<Result<List<ItemOrder>, Failure>> retriveOrders(String itemName);
}
17 changes: 17 additions & 0 deletions lib/features/codex/domian/usercases/get_orders.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:market_client/market_client.dart';
import 'package:oxidized/oxidized.dart';

import '../../../../core/error/failures.dart';
import '../../../../core/usecases/usecases.dart';
import '../repositories/market_repository.dart';

class GetOrders extends Usecase<List<ItemOrder>, String> {
const GetOrders(this.marketRepository);

final MarketRepository marketRepository;

@override
Future<Result<List<ItemOrder>, Failure>> call(String params) {
return marketRepository.retriveOrders(params);
}
}
Loading