Compare commits

...

149 Commits

Author SHA1 Message Date
aa8717946a Several fixes
- CurrencySelectionActivity renamed to CurrencyListActivity
- Allow refresh from the Update snackbar button in Summary after an error
- Code cleaning
- Typo
2018-11-19 16:43:42 +01:00
cb428937d4
Fix decode feature in the app (MUST BE CHECKED) 2018-10-02 15:36:56 +02:00
1cb7c03d63 Remove useless code 2018-09-02 02:08:59 +02:00
3e56c6f90e Prepare suffix code for some inputs 2018-09-02 01:54:48 +02:00
f837372551 Add icon displaying animation 2018-09-02 01:03:29 +02:00
8ca63b5e85 Rework icon loading
- Icons are now downloaded after displaying the whole list
2018-09-01 23:31:17 +02:00
e6d69a01ce Update chart color definition algorithm
Everything comes now from the MoodlUtilBox
2018-09-01 23:30:19 +02:00
16eafc075a Update version name for BETA 2018-08-29 01:12:47 +02:00
b97b8e7645 Add logos to exchange accounts list 2018-08-29 01:11:25 +02:00
2a4ba215e6 Fix 'infinity' balance percentage when hiding the balance 2018-08-28 13:43:14 +02:00
9395ec7425 Fix transaction history not displaying correctly
- Fix deducted transactions not being displayed
- Fix pairs not displayed properly
2018-08-27 04:01:12 +02:00
7623012353 Fix total value calculus and allow fiat display
- Fix Deduct switch not being updated when editing a transaction

Previous commit tested and working
2018-08-27 03:41:33 +02:00
4738a65dcc [Untested] Fix balance deductions 2018-08-27 02:48:16 +02:00
2654b044b2 Minor fixs
- Icon size fix
- Fix details activity crash
2018-08-24 04:05:05 +02:00
dd9f4d2141 Rework labels in transaction history
- Summary now updates after importing data
- Fix crash when exiting the details activity too quickly
2018-08-22 21:27:58 +02:00
518df666f4 Multiple fixs
[DetailsActivity]
- Fix crash when finishing the activity before all transactions and trades are updated

[MarketCapitalizationActivity]
- Fix some views not visible for little screens

[RecordTransactionActivity]
- Fix crash when editing a sell transaction
2018-08-21 02:00:09 +02:00
ac7fb545ec [DetailsActivity] Merge Transactions and Trades in the same list 2018-08-21 00:19:29 +02:00
e80c9f4046 Code sorting 2018-08-20 22:45:03 +02:00
d79a76f13b [DetailsActivity] Enable binance trade update
- Add support for multiple binance accounts
2018-08-20 22:35:37 +02:00
b25e44d3ef Fix transaction edition
- Fee format was not displayed correctly in Buy and Sell tabs
2018-08-20 21:54:12 +02:00
10c3a0a67b UI fix
[RecordTransactionActivity]
- Fix tab color when editing a transaction
- Disable tab swiping
- Fix crash when editing a sell transaction
2018-08-20 20:32:59 +02:00
4c65596718 Add transaction indicator 2018-08-20 18:12:35 +02:00
ffd103fad3 Fix transfer equation 2018-08-20 16:16:23 +02:00
b22aa6bc12
Merge pull request #8 from TanguyHerbron/unstable
Rework SettingsActivity and RecordTransactionActivity + several fixs
2018-08-20 05:10:06 +02:00
2dd608ecc8 Complete french translation 2018-08-20 04:54:50 +02:00
7f0518a96a Transfer edition and several fixs
[RecordTransactionActivity]
- Fix Buy tab crash when editing a transaction
- Fix Sell transaction edition not working at all
- Add Transfer edition
- Add 'Deduct from holdings' switch to all tabs

[SettingsActivity]
- Fix manual entires import not filling all database columns

[General]
- Fix balance calculation not working properly
2018-08-20 04:54:16 +02:00
f907a4bdb1 Update transfer tab in RecordTransactionActivity
- Add backend code to the Transfer tab

TODO :
- Support for %/fixed fees for transfers
- Edition support for transfers
2018-08-19 02:48:52 +02:00
40210fdbf0 Code cleaning / sorting 2018-08-19 02:46:53 +02:00
43171cd428 Fix RecordTransactionActivity crash
- The intent is now cleared after editing a transaction, avoiding a crash in certain scenarios
2018-08-19 02:15:48 +02:00
8ba9cc2ff9 Update icon
Smoother corners
2018-08-18 21:31:43 +02:00
1d4324bec2 Update transfert tab in RecordTransactionActivity
- Prepare 'from' and 'to' fields
- Setup date field

- Update tab text colors
2018-08-18 02:34:02 +02:00
de38e5dea4 Remove layout duplicates 2018-08-17 05:14:23 +02:00
b14b98eb97 Fix balance calculus for sell transaction 2018-08-17 04:52:27 +02:00
cdff187910 Fix sell fees equation 2018-08-17 04:44:49 +02:00
1efbaea351 Update Sell tab in the RecordTransactionActivity allowing to register sell transaction 2018-08-17 04:38:49 +02:00
1f433ba708 Fix buy fees display in the RecordTransactionActivity
- Fix fixed fees equation
2018-08-17 03:09:45 +02:00
89246e0919 Fix amount and total value equation when adding a fee while recording a transaction 2018-08-16 04:06:15 +02:00
6194ff501a Fix price update when picking a new date while recording a transaction 2018-08-16 03:29:14 +02:00
e194d362ba Add badge in the drawer when an exchange account is disabled 2018-08-16 03:23:19 +02:00
727e803b8b Fix balance not being displayed properly for some fee format 2018-08-16 02:50:40 +02:00
f32270cc4b RecordTransactionActivity fixs
- Dynamic amount when filling the total value
- Fix fee calcul when using the pair percentage option
2018-08-16 02:24:29 +02:00
e308e962d7 Fix fee format when editing a transaction 2018-08-15 22:39:12 +02:00
4bdffe22c4 Fix negative balance not displaying 2018-08-15 22:37:43 +02:00
91418b73fa Fix SDK 19 crash 2018-08-15 04:23:54 +02:00
85dd10a177 Fix app crash for SDK 19 2018-08-15 04:14:04 +02:00
df9ab11410 Fix transaction edition
- Fix crash when trying to edit a transaction
- Update the code when editing a transaction to match the new interface
2018-08-15 02:51:28 +02:00
74cae8fa67 Update database design 2018-08-14 21:19:01 +02:00
3a1ac3c80b Major updates
- Fix code typos
- Add a 'fromSym' field in the transactions table
- Fix translation in the drawer

[RecordTransactionActivity rework]
- New currency selection
- Add Exchange selection
- Add corresponding Pair selection
- Add tabs to select Buy/Sell/Transaction
> Buy fragment
- Add note field
- Add fee format selection
- Limit date selection to the past (it's no longer possible to add a futur transaction)
- Auto fill the price after date selection
2018-08-14 04:14:18 +02:00
7b5fd6e786 Update french translation 2018-08-04 05:05:12 +02:00
d0041a87ba Fix cardview margins for 19-23 SDK 2018-08-04 04:01:06 +02:00
1d18847c3c Fix AddExchangeActivity crash for 19-23 SDK
- Update the exchange connexion error icon
2018-08-04 03:54:45 +02:00
ae3ab48c58 Fix compatibility issues for 19-23 SDK 2018-08-04 03:35:35 +02:00
cf8cc29329 Add exchange/pair selection after each parent choice in the RecordTransactionActivity 2018-08-04 03:04:07 +02:00
ac3ad43775 Details are now accessible even when there is no chart data 2018-08-03 16:17:15 +02:00
92f08e00ed Update code with new interfaces for a clearer code (I hope so...)
- Preview of the RecordTransactionActivity buying UI
- MarketCapManager.java and CoinmarketCapAPIManager are now merged
2018-08-03 03:22:20 +02:00
10888c4c54 Rework RecordTransactionActivity's UI 2018-08-02 13:12:05 +02:00
b919e164e5 Exchange activities fix
- Refresh balance after exchange update
- Invalid HitBTC accounts are now disabled after balance refresh
2018-08-01 16:14:20 +02:00
34ff605de2 Fix exchange list not updating correctly 2018-08-01 16:03:43 +02:00
3efa225e5c Add support for multiple Binance accounts
- Small UI improvement for the Exchange list activity
- New Binance API jar created from this [fork](https://github.com/TanguyHerbron/binance-java-api)
- Disable VET display, waiting for the swap to be completely done
2018-08-01 15:57:30 +02:00
2d12cc3dbe Fix exchange connexion status not showing properly 2018-08-01 13:56:54 +02:00
b7d10011ef Fix exchange type not being processed properly 2018-08-01 13:08:16 +02:00
8778290135 Add API keys importation 2018-08-01 01:17:29 +02:00
380716f7ea Exchange config rework
- Fix crash when binance sync error
- New exchange list UI
- New exchange configuration UI
- Fix gradient background for Settings activity

The new exchange configuration interface allows you to add (it should work) multiple accounts for each exchange
If an account's keys are incorrect, the account and disabled and it's notified in the exchange list
You can edit the exchange account later from the exchange list activity
2018-08-01 01:02:41 +02:00
af2eeed241 Merge branch 'unstable' of https://github.com/TanguyHerbron/Coinfolio into unstable 2018-07-31 13:17:33 +02:00
a64aed4729 Update exchange activity 2018-07-31 13:16:42 +02:00
38723b7dca
Merge pull request #7 from TanguyHerbron/master
Update unstable to correct some bugs hot fixed
2018-07-31 13:14:30 +02:00
93f0a700fb WIP
- Prepare RecordTransactionActivity rework
- Lock Touch ID if not supported/not configured
- Prepare API storage rework
- Fix CurrencyTickerList and CurrencyDetailsList crash
-
2018-07-31 01:48:03 +02:00
6fe8831c69 Several fixes/adjustments
- LineCharts are now smooth
- The splashscreens works 'properly' even when there is no cached icons
- Edit mode is disabled when adding a coin in the watchlist
- Add option to clear cache in the settings menu when in debug mode
2018-07-31 01:19:00 +02:00
533aea5bb6 Ripple effect on watchlist/holdings add button 2018-07-23 23:44:44 +02:00
188d924c18 Watchlist : Edit button animations 2018-07-23 19:43:42 +02:00
1c670d6e5d
Merge pull request #6 from TanguyHerbron/master
Update the branch for new code coming
2018-07-21 21:56:30 +02:00
08434128b1 Fix status bar flash when starting the app 2018-07-21 21:49:41 +02:00
2df677c947 Add gradient to the status bar
- Rework some labels
- Gradient orientation changed
2018-07-21 21:26:58 +02:00
582a155c8b Fix refreshing indicator not being displayed properly in the holding section 2018-07-21 18:26:41 +02:00
7f1a318a70 Data backup UI rework
- Fix balance hiding not working properly after restarting the app
- An error is displayed when no proper password is entered for backup encryption
- Add Watchlist, Manual entries and API keys backup and restore options
- Add wipe old data for Watchlist, Manual entries and API keys option
- Add encode checker to know whether or not the backup is encrypted
- Fix unproper import/export labels
- Add round corners to the top of each main layout (Holdings/Watchlist/MarketCap/List)
2018-07-21 14:56:26 +02:00
b53d52daeb Update placeholders and translations 2018-07-19 23:59:29 +02:00
47c4fb0daf Backup encryption feature
- Add encryption option when exporting and importing backup
- Add wipe data option when importing backup
2018-07-18 23:54:04 +02:00
f8bb7b0487 Add some label translations (EN/FR) 2018-07-17 00:43:45 +02:00
aa10defb03 Major detail activity fix
- Fix details activity chart loading error
- Fix some non translated strings
2018-07-17 00:33:29 +02:00
2b165ba2a0 Bug fixes
- Rework SettingsActivity code to make it clearer
- Fix crash when loading app icon as default icon
2018-07-15 21:20:26 +02:00
7946ba4897 New features
- App loading animation generated from cached icons
- Import backups (data format will be reworked)
- Fix cryptocompare crash because of an API update
2018-07-15 00:32:51 +02:00
e173e48612 Export feature
You can now export (it's an early stage) your manual entries to a file to restore it later
- Choose where to put your backup
- Code for encrypting data (will be enabled soon)
- Update version number to 0.0.6
2018-07-11 23:57:55 +02:00
de6fc36e6c Import data implementation (begining)
- Adds an interface for the data import feature (not final)
- Can read data from a manually created backup file
2018-07-09 23:47:30 +02:00
7b9282bfef Rework settings activity
- Clearer settings activity
- Data import/export buttons
2018-07-05 23:26:40 +02:00
87d02b5365 Code cleaning 2018-06-18 08:44:04 +02:00
e8d30e41f8 Fix fluctuation percentage 2018-06-17 19:30:33 +02:00
91a1551fa7 Fix color glich 2018-06-17 03:45:26 +02:00
5a512a304a Fix margins and paddings 2018-06-17 02:12:33 +02:00
40e511a576
Merge pull request #5 from TanguyHerbron/MPAndroidChart_full
Merge pull request #4 from TanguyHerbron/FragmentRework
2018-06-16 21:31:04 +02:00
0cd2053bb4
Merge pull request #4 from TanguyHerbron/FragmentRework
Fragment rework
2018-06-16 21:29:59 +02:00
3827329ca9 Fix delete animation in listview | Add input security while registering a transaction 2018-06-12 23:28:07 +02:00
cff73dac49 Minor fixs
- Fix crash when fields in the Record activity are field with unexpected infos
- Fix soft buttons being overlapped by some activities
- Fix NaN bug displayed in the drawer when hiding balance while having 0$
- Fix activities action bar not being displayed properly
2018-06-08 21:50:07 +02:00
75da1ee9e8 Translation & fix
- Add complete french translation
- Fix app crash when adding a transaction with empty field(s)
2018-06-05 20:05:48 +02:00
0c0cfff731 Add Toast to show when a Currency is already in the watchlist 2018-06-05 08:41:42 +02:00
3b894c634b Fix duplicated watchlist elements 2018-06-05 08:38:47 +02:00
7505d8a1be Icon & features
- Update Icon
- Add balance value in the drawer
2018-06-04 02:57:46 +02:00
38a84e0f1e Fix fragment glitch when using the back button 2018-06-04 02:02:55 +02:00
142b00aff5 Add reorder option for Watchlist currencies | New edit buttons 2018-06-04 01:48:53 +02:00
856bce59ac Update version name and code 2018-06-01 19:54:29 +02:00
7b51de4f26 Update margins for old versions 2018-06-01 19:46:47 +02:00
d29f808ca8 Update package name to match Google Play's developer name 2018-06-01 19:42:33 +02:00
79484abb83 Fix SearchView not updating ListView in search activity 2018-06-01 19:39:55 +02:00
b935cfa89f Update version name
Fix SDK 19 crashs
2018-05-30 16:58:46 +02:00
2339a98f64 Min SDK > 19 (To be tester) 2018-05-29 14:55:24 +02:00
6a8ecfea74 Fix pixel sized layouts
- Move dp to px converter to moodlbox
- Fix details activity icon size generation
2018-05-29 14:38:16 +02:00
122a487f29 Fix deprecated methods 2018-05-29 11:43:27 +02:00
418debc44f Clean resources 2018-05-29 00:16:14 +02:00
8a347ceef9 Fix overview UI freeze | Coin list now looks like other lists 2018-05-28 17:13:24 +02:00
aeb9c9cd18 Fix & improvements
- Added coin list in navigation drawer
- Rework the coin list interface to load dynamicly
- Fix dust not being counted in balance
2018-05-28 01:34:44 +02:00
d0069f4ad5 Optimization
- CurrencyDetailsList is now a Singleton class
- CurrencyTickerList is now a Singleton class
2018-05-27 01:03:59 +02:00
fcb288e0ed Allow full list loading in selection activity 2018-05-27 00:29:28 +02:00
c09fa8ca6f Add dynamic color generation to marketp cap activity 2018-05-26 18:51:42 +02:00
9218d54261 Add active markets/cryptocurrencies at marketcap activity 2018-05-26 17:17:33 +02:00
2cfb2df9d3 Marketp cap activity improvements
- Add icon review
- Add "global" and "others" info
- Add dominance percentage
2018-05-26 17:01:36 +02:00
9845edd8cb Add coin icon preview for market capitalization details 2018-05-26 16:12:07 +02:00
4986091644 Update icon code 2018-05-26 01:26:23 +02:00
241362fe8c UI and performance improvements
- Add cache loading for icons
- Rework Market capitalization activity UI
2018-05-25 21:16:55 +02:00
b46e9cbe3f Fix watchlist edition not working 2018-05-23 17:25:43 +02:00
a46ad91f79 Fix watchlist loading
- Watchlist was no longer refreshing
- No loading indicator when first loading the fragment
2018-05-23 17:17:33 +02:00
54e6bb4e9e Add hide balance switch in drawer 2018-05-23 14:56:32 +02:00
bdc36f149f Drawer improvement
- Rework fragment loading
- Add drawer header
- Add sub category for settings (more to come)
- Rework watchlist update with asynchronous work
2018-05-23 11:08:30 +02:00
5e2c2668db Add drawer header 2018-05-23 08:08:06 +02:00
067ce01183 Drawer settings > First shot
- Remove bottom navigation view
- Add drawer layout
- Fix toolbar icon sizes
- Add settings activity in drawer layout
2018-05-21 04:20:38 +02:00
984956e535 Update graddle | Display marketcap details | Fix marketcap piechart click crash 2018-05-18 12:24:10 +02:00
44333e55f7 Some market capitalization details 2018-05-17 00:47:30 +02:00
8f45e65666 Several fixs
- Rework DetailsActivity code
- Fix Home and Watchlist UI generation
2018-05-16 01:09:55 +02:00
a5f2d9a1fd Update Home fragment in DetailsActivity 2018-05-14 02:01:28 +02:00
0ab4cb15a1 Fix card generation | Preparing Details fragments
Have to reinstall Windows, non usable commit as is
2018-05-13 17:47:08 +02:00
8c9c6b4cd0 Add watchlist transition animations 2018-05-13 04:03:16 +02:00
e5ab35b9bd Fix IOTA history loading | Fix too ligh chart colors 2018-05-13 03:40:56 +02:00
84a8c98dd4 Updates
- Remove HomeLayoutGenerator class
- Add CurrencyCardview which overrides Cardview
- Fix trading and general balance syncing for HitBTC
2018-05-13 03:23:08 +02:00
d2aaec536d Add volume chart highlight synchronization | fix transactions order 2018-05-09 04:11:53 +02:00
db013dab1e Hide blank categories in details activity 2018-05-09 02:56:26 +02:00
460eb1aa14 Fix CoinMarketCap v2 API implementation 2018-05-09 02:49:19 +02:00
0927d6629c Update CoinMarketCap API to V2 | Fix HitBTC balance synchronization 2018-05-09 01:49:04 +02:00
373a944e41 Fix and improvements
- Clear code
- Add Mooblbox for toolbox methods
- Add minimum value settings to display a currency (ex : everything above 0.01)
- Fix Market capitalization padding
- Reduce FPS drop while reloading data
- Fix refresh for 1H, 3H and 1D charts in detail activity
2018-05-05 16:53:22 +02:00
18da197cf6 Set theme jekyll-theme-minimal 2018-05-02 14:50:51 +02:00
6d3e5b7bfd Fix Binance trade synchronization 2018-04-29 19:59:06 +02:00
009dc09eca Add loading indicator for trades 2018-04-29 15:29:59 +02:00
680840b262 Add edit transaction option in details activity 2018-04-27 16:25:51 +02:00
a082bb3d99 Transparent status bar 2018-04-26 12:33:36 +02:00
edbb27dd37 First reword of record activity 2018-04-25 15:48:48 +02:00
19872f5609 Add fees for sent transaction 2018-04-24 23:19:57 +02:00
ee8ba428d7 ListView for Transaction history 2018-04-24 16:08:05 +02:00
ec73925720 Add dynamic trade loading 2018-04-24 15:12:51 +02:00
eeca570566 Update logo 2018-04-24 12:33:46 +02:00
7d9a15ea4c Remove binaries 2018-04-23 18:01:37 +02:00
28470e08f8 Rebrand to Moodle 2018-04-23 17:56:26 +02:00
dc4d5b48c6 . 2018-04-23 16:17:09 +02:00
299 changed files with 17430 additions and 8352 deletions

75
.gitignore vendored
View File

@ -1,10 +1,69 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
# Built application files
*.apk
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/caches
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# Google Services (e.g. APIs or Firebase)
google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md

136
.idea/assetWizardSettings.xml generated Normal file
View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WizardSettings">
<option name="children">
<map>
<entry key="imageWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="imageAssetPanel">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="actionbar">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="image">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="paddingPercent" value="-10" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="assetType" value="IMAGE" />
<entry key="imageAsset" value="D:\Projets Adobe\Photoshop\Moodl_background_textonly.png" />
<entry key="outputName" value="moodl_background" />
<entry key="theme" value="CUSTOM" />
<entry key="themeColor" value="ffffff" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="launcher">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="foregroundImage">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="scalingPercent" value="72" />
<entry key="trimmed" value="true" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="backgroundAssetType" value="COLOR" />
<entry key="backgroundColor" value="004e92" />
<entry key="backgroundLayerName" value="ic_launcher_background" />
<entry key="foregroundImage" value="D:\Projets Adobe\Photoshop\Moodl_icon_white.png" />
<entry key="foregroundLayerName" value="ic_launcher_foreground" />
<entry key="outputName" value="ic_launcher_moodl" />
<entry key="previewDensity" value="MEDIUM" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="outputIconType" value="ACTIONBAR" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="vectorWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="vectorAssetStep">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="clipartAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="url" value="jar:file:/C:/Program%20Files/Android/Android%20Studio/plugins/android/lib/android.jar!/images/material_design_icons/navigation/ic_arrow_upward_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="color" value="ffffff" />
<entry key="outputName" value="exchange_logo_hitbtc" />
<entry key="sourceFile" value="D:\Téléchargement\hitbtc.svg" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</component>
</project>

BIN
.idea/caches/build_file_checksums.ser generated Normal file

Binary file not shown.

29
.idea/codeStyles/Project.xml generated Normal file
View File

@ -0,0 +1,29 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
</code_scheme>
</component>

2
.idea/gradle.xml generated
View File

@ -5,7 +5,7 @@
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="C:\Program Files\Android\Android Studio\gradle\gradle-4.1" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-4.9" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

27
.idea/misc.xml generated
View File

@ -1,15 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" value="F:/Export AS" />
<option name="OPTION_SCOPE" value="protected" />
<option name="OPTION_HIERARCHY" value="true" />
<option name="OPTION_NAVIGATOR" value="true" />
<option name="OPTION_INDEX" value="true" />
<option name="OPTION_SEPARATE_INDEX" value="true" />
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
<option name="OPTION_DEPRECATED_LIST" value="true" />
<option name="OTHER_OPTIONS" />
<option name="HEAP_SIZE" />
<option name="LOCALE" />
<option name="OPEN_IN_BROWSER" value="true" />
<option name="OPTION_INCLUDE_LIBS" value="false" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<list size="5">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
@ -24,7 +43,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

2
.idea/modules.xml generated
View File

@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Coinfolio.iml" filepath="$PROJECT_DIR$/Coinfolio.iml" />
<module fileurl="file://$PROJECT_DIR$/Moodl.iml" filepath="$PROJECT_DIR$/Moodl.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>

12
.idea/statistic.xml generated
View File

@ -1,20 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Statistic">
<option name="fileTypes" value="class;svn-base;svn-work;Extra;gif;png;jpg;jpeg;bmp;tga;tiff;ear;war;zip;jar;iml;iws;ipr;bz2;gz;gitignore;gradle;md;pro;properties;" />
<option name="fileTypes" value="class;svn-base;svn-work;Extra;gif;png;jpg;jpeg;bmp;tga;tiff;ear;war;zip;jar;iml;iws;ipr;bz2;gz;ap;apk;bin;dex;flat;gitignore;gson;json;md;pro;store;ttf;txt;ap_;" />
<option name="excludedDirectories">
<list>
<option value="$PROJECT_DIR$/build" />
<option value="$PROJECT_DIR$/.idea" />
<option value="$PROJECT_DIR$/.gradle" />
<option value="$PROJECT_DIR$/export" />
<option value="$PROJECT_DIR$/gource" />
<option value="$PROJECT_DIR$/gradle" />
<option value="$PROJECT_DIR$/libs" />
<option value="$PROJECT_DIR$/.idea" />
<option value="$PROJECT_DIR$/.gradle" />
<option value="$PROJECT_DIR$/app/build" />
<option value="$PROJECT_DIR$/app/release" />
<option value="$PROJECT_DIR$/app/src/androidTest" />
<option value="$PROJECT_DIR$/app/src/test" />
<option value="$PROJECT_DIR$/app/src/androidTest" />
<option value="$PROJECT_DIR$/app/build" />
</list>
</option>
</component>

2
.idea/vcs.xml generated
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Coinfolio Copyright (C) 2018 Tanguy Herbron
Moodl Copyright (C) 2018 Tanguy Herbron
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

View File

@ -1,7 +1,7 @@
# Coinfolio ![State](https://img.shields.io/badge/State-in%20development-red.svg)
This repository contains the source code of Coinfolio
<!--<img src="https://github.com/TanguyHerbron/Coinfolio/blob/master/app/src/main/icon_coinfolio-web.png" width="100">-->
# Moodl ![State](https://img.shields.io/badge/State-in%20development-red.svg)
This repository contains the source code of Moodl
<!--<img src="https://github.com/TanguyHerbron/Moodl/blob/master/app/src/main/ic_launcher_moodl-web.png" width="100">-->
# What is coinfolio ?
# What is moodl ?
Coinfolio is a handy cryptocurrency and ICO portfolio tracker. With its easy to use interface, you can watch your cryptocurrencies and ICOs fluctuate during the day/week/month or year. Coinfolio allows you to keep up with the Global Market Capitalization as well and Exchanges statistics.
Moodl is a handy cryptocurrency and ICO portfolio tracker. With its easy to use interface, you can watch your cryptocurrencies and ICOs fluctuate during the day/week/month or year. Moodl allows you to keep up with the Global Market Capitalization as well and Exchanges statistics.

View File

@ -1 +1 @@
theme: jekyll-theme-cayman
theme: jekyll-theme-minimal

View File

@ -3,47 +3,68 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.nauk.coinfolio"
minSdkVersion 23
applicationId "com.herbron.moodl"
minSdkVersion 19
targetSdkVersion 27
versionCode 1
versionName "0.0.1"
versionCode 7
versionName "0.1.7"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
dataBinding {
enabled = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
lintOptions {
checkReleaseBuilds false
//disable 'MissingTranslation'
}
}
}
sourceSets {
main.java.srcDirs += 'src/main/binance/src'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.0'
implementation 'com.android.support:design:27.1.0'
implementation 'com.android.support:cardview-v7:27.1.0'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.mcxiaoke.volley:library:1.0.19'
implementation 'com.diogobernardino:williamchart:2.5.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:support-v4:27.1.0'
implementation 'com.android.support:palette-v7:27.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.android.support:palette-v7:27.1.1'
implementation 'com.daimajia.swipelayout:library:1.2.0@aar'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.8.5'
implementation 'com.fasterxml.jackson.core:jackson-core:2.8.5'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.8.5'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.2.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
implementation 'org.apache.commons:commons-lang3:3.6'
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
implementation 'com.mattprecious.swirl:swirl:1.1.0'
implementation 'com.wdullaer:materialdatetimepicker:3.5.2'
implementation 'com.wdullaer:materialdatetimepicker:3.6.3'
implementation 'com.jmedeisis:draglinearlayout:1.1.0'
implementation 'com.applandeo:material-file-picker:1.0.0'
implementation 'com.daasuu:EasingInterpolator:1.0.0'
implementation 'com.android.support:support-vector-drawable:27.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation files('../libs/binance-api.jar')
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation files('../libs/binance-api-forked.jar')
implementation files('../libs/commons-codec-1.11.jar')
}

Binary file not shown.

View File

@ -1 +0,0 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1},"path":"app-release.apk","properties":{"packageId":"com.nauk.coinfolio","split":"","minSdkVersion":"23"}}]

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio;
package com.herbron.moodl;
import android.content.Context;
import android.support.test.InstrumentationRegistry;

View File

@ -1,26 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nauk.coinfolio">
package="com.herbron.moodl">
<uses-feature android:name="android.hardware.fingerprint"
android:required="false"/>
<uses-feature
android:name="android.hardware.fingerprint"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/icon_coinfolio"
android:icon="@mipmap/ic_launcher_moodl"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:roundIcon="@mipmap/ic_launcher_moodl"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".Activities.HomeActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTop">
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -32,18 +34,19 @@
android:label="@string/title_activity_settings"
android:screenOrientation="portrait" />
<activity
android:name=".Activities.CurrencySelectionActivity"
android:name=".Activities.CurrencyListActivity"
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.nauk.coinfolio.Activities.HomeActivity"/>
android:value="com.herbron.moodl.Activities.HomeActivity" />
</activity>
<activity
android:name=".Activities.RecordTransactionActivity"
android:screenOrientation="portrait">
android:screenOrientation="portrait"
android:theme="@style/InputActivityTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.nauk.coinfolio.Activities.HomeActivity"/>
android:value="com.herbron.moodl.Activities.HomeActivity" />
</activity>
<activity
android:name=".Activities.CurrencyDetailsActivity"
@ -51,8 +54,14 @@
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.nauk.coinfolio.Activities.HomeActivity"/>
android:value="com.herbron.moodl.Activities.HomeActivity" />
</activity>
<activity
android:name=".Activities.ExchangeListActivity"
android:label="@string/title_activity_exchange_list"
android:theme="@style/InputActivityTheme"/>
<activity android:name=".Activities.AddExchangeActivity"
android:theme="@style/InputActivityTheme"></activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,180 @@
package com.herbron.moodl.Activities;
import android.content.Intent;
import android.support.design.widget.TextInputEditText;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.R;
public class AddExchangeActivity extends AppCompatActivity {
private LinearLayout setupExchangeLayout;
private Spinner exchangeSpinner;
private DatabaseManager databaseManager;
private TextInputEditText accountLabelEditText;
private TextInputEditText accountDescriptionEditText;
private TextInputEditText publicKeyEditText;
private TextInputEditText secretKeyEditText;
private AppCompatButton saveExchangeButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getApplicationContext().setTheme(R.style.InputActivityTheme);
setContentView(R.layout.activity_add_exchange);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
databaseManager = new DatabaseManager(getBaseContext());
exchangeSpinner = findViewById(R.id.exchange_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.supported_exchanges, R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
setupExchangeLayout = findViewById(R.id.exchange_setup_layout);
exchangeSpinner.setAdapter(adapter);
Intent callingIntent = getIntent();
if(callingIntent.getBooleanExtra("isEdit", false))
{
startExchangeEditionForId(callingIntent.getIntExtra("exchangeId", -1));
}
else
{
exchangeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
loadLayoutFor(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
setupBackButton();
}
private void loadLayoutFor(int exchangeType)
{
setupExchangeLayout.removeAllViews();
exchangeSpinner.setSelection(exchangeType);
switch (exchangeType)
{
case DatabaseManager.BINANCE_TYPE:
setupExchangeLayout = (LinearLayout) LayoutInflater.from(getBaseContext()).inflate(R.layout.binance_exchange_setup_layout, setupExchangeLayout, true);
bindSetupViews();
break;
case DatabaseManager.HITBTC_TYPE:
setupExchangeLayout = (LinearLayout) LayoutInflater.from(getBaseContext()).inflate(R.layout.hitbtc_exchange_setup_layout, setupExchangeLayout, true);
bindSetupViews();
break;
}
}
private void startExchangeEditionForId(int exchangeId)
{
Exchange exchangeInfos = databaseManager.getExchangeFromId(exchangeId);
loadLayoutFor(exchangeInfos.getType());
exchangeSpinner.setEnabled(false);
accountLabelEditText.setText(exchangeInfos.getName());
accountDescriptionEditText.setText(exchangeInfos.getDescription());
publicKeyEditText.setText(exchangeInfos.getPublicKey());
secretKeyEditText.setText(exchangeInfos.getPrivateKey());
saveExchangeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isEditTextFilled(accountLabelEditText) && isEditTextFilled(publicKeyEditText) && isEditTextFilled(secretKeyEditText))
{
PreferencesManager preferencesManager = new PreferencesManager(getBaseContext());
preferencesManager.setMustUpdateSummary(true);
databaseManager.deleteExchangeAccountFromId(exchangeInfos.getId());
databaseManager.addExchange(accountLabelEditText.getText().toString(), exchangeSpinner.getSelectedItemPosition()
, accountDescriptionEditText.getText().toString(), publicKeyEditText.getText().toString()
, secretKeyEditText.getText().toString());
finish();
}
}
});
}
private void bindSetupViews()
{
accountLabelEditText = findViewById(R.id.account_label_editText);
accountDescriptionEditText = findViewById(R.id.account_description_editText);
publicKeyEditText = findViewById(R.id.publicKey_editText);
secretKeyEditText = findViewById(R.id.secretKey_editText);
saveExchangeButton = findViewById(R.id.saveExchangeButton);
saveExchangeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isEditTextFilled(accountLabelEditText) && isEditTextFilled(publicKeyEditText) && isEditTextFilled(secretKeyEditText))
{
PreferencesManager preferencesManager = new PreferencesManager(getBaseContext());
preferencesManager.setMustUpdateSummary(true);
databaseManager.addExchange(accountLabelEditText.getText().toString(), exchangeSpinner.getSelectedItemPosition()
, accountDescriptionEditText.getText().toString(), publicKeyEditText.getText().toString()
, secretKeyEditText.getText().toString());
finish();
}
}
});
}
private boolean isEditTextFilled(TextInputEditText editText)
{
if(editText.getText().toString().equals("") || editText.getText().toString().equals(" "))
{
editText.setError(getResources().getString(R.string.must_be_filled));
return false;
}
return true;
}
private void setupBackButton()
{
ImageButton backButton = findViewById(R.id.back_button);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio.Activities;
package com.herbron.moodl.Activities;
import android.content.res.Configuration;
import android.os.Bundle;

View File

@ -0,0 +1,280 @@
package com.herbron.moodl.Activities;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DetailsActivityPagerAdapter;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.R;
import java.util.Objects;
import static com.herbron.moodl.MoodlBox.numberConformer;
import static java.lang.Math.abs;
/**Create a Parcelable**/
public class CurrencyDetailsActivity extends AppCompatActivity {
private ViewPager viewPager;
private Currency currency;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
viewPager.setCurrentItem(0);
return true;
case R.id.navigation_dashboard:
viewPager.setCurrentItem(1);
return true;
case R.id.navigation_notifications:
viewPager.setCurrentItem(2);
return true;
}
return false;
}
};
@Override
public void onBackPressed()
{
Intent intent = new Intent(this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
finish();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if(viewPager.getCurrentItem() == 0)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
finishAfterTransition();
}
}
else
{
finish();
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_currency_details);
currency = getIntent().getParcelableExtra(getBaseContext().getString(R.string.currency));
viewPager = findViewById(R.id.vfCurrencyDetails);
final DetailsActivityPagerAdapter adapter = new DetailsActivityPagerAdapter(getSupportFragmentManager(), 3);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
BottomNavigationView navigation = findViewById(R.id.navigation_details);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
setupActionBar();
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(!navigation.getMenu().getItem(position).isChecked())
{
navigation.getMenu().getItem(position).setChecked(true);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void setupActionBar()
{
if(currency.getBalance() == 0)
{
setTitle(" " + currency.getName());
}
else
{
setTitle(" " + currency.getName() + " | " + numberConformer(currency.getBalance()));
}
Objects.requireNonNull(getSupportActionBar()).setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME |
ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_USE_LOGO);
Bitmap result = Bitmap.createBitmap(150, 150, currency.getIcon().getConfig());
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(ContextCompat.getColor(this, R.color.white));
Canvas canvas = new Canvas(result);
canvas.drawCircle(result.getHeight()/2, result.getWidth()/2, 75, paint);
canvas.drawBitmap(Bitmap.createScaledBitmap(currency.getIcon(), 100, 100, false), result.getHeight()/2 - 50, result.getWidth()/2 - 50, null);
getSupportActionBar()
.setIcon(new BitmapDrawable(getResources(),
Bitmap.createScaledBitmap(result
, (int) MoodlBox.convertDpToPx(25, getResources())
, (int) MoodlBox.convertDpToPx(25, getResources())
, false)));
}
}
/*for(int i = 0; i < dataChartList.size(); i++)
{*/
/*if(counter == offset)
{
calendar.setTimeInMillis(dataChartList.get(i).getTimestamp()*1000);
switch (pointFormat)
{
case HOUR:
hour = String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
minute = String.valueOf(calendar.get(Calendar.MINUTE));
if(hour.length() < 2)
{
hour = "0" + hour;
}
if(minute.length() < 2)
{
minute = "0" + minute;
}
lineSet.addPoint(hour + ":" + minute, (float) dataChartList.get(i).getOpen());
break;
case DAY:
int dayIndex = calendar.get(Calendar.DAY_OF_WEEK)+1;
switch (dayIndex)
{
case Calendar.MONDAY:
dayName = "Mon";
break;
case Calendar.TUESDAY:
dayName = "Tue";
break;
case Calendar.WEDNESDAY:
dayName = "Wed";
break;
case Calendar.THURSDAY:
dayName = "Thu";
break;
case Calendar.FRIDAY:
dayName = "Fri";
break;
case Calendar.SATURDAY:
dayName = "Sat";
break;
case Calendar.SUNDAY:
dayName = "Sun";
break;
}
lineSet.addPoint(dayName, (float) dataChartList.get(i).getOpen());
break;
case MONTH:
dayNumber = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)+1);
monthNumber = String.valueOf(calendar.get(Calendar.MONTH)+1);
if(dayNumber.length() < 2)
{
dayNumber = '0' + dayNumber;
}
if(monthNumber.length() < 2)
{
monthNumber = '0' + monthNumber;
}
lineSet.addPoint(dayNumber + "/" + monthNumber, (float) dataChartList.get(i).getOpen());
break;
case YEAR:
int mb = calendar.get(Calendar.MONTH);
switch (mb)
{
case Calendar.JANUARY:
monthName = "Jan";
break;
case Calendar.FEBRUARY:
monthName = "Feb";
break;
case Calendar.MARCH:
monthName = "Mar";
break;
case Calendar.APRIL:
monthName = "Apr";
break;
case Calendar.MAY:
monthName = "May";
break;
case Calendar.JUNE:
monthName = "Jun";
break;
case Calendar.JULY:
monthName = "Jul";
break;
case Calendar.AUGUST:
monthName = "Aug";
break;
case Calendar.SEPTEMBER:
monthName = "Sep";
break;
case Calendar.OCTOBER:
monthName = "Oct";
break;
case Calendar.NOVEMBER:
monthName = "Nov";
break;
case Calendar.DECEMBER:
monthName = "Dec";
break;
}
lineSet.addPoint(monthName, (float) dataChartList.get(i).getOpen());
break;
}
counter = 0;
}
else
{
counter++;
lineSet.addPoint("", (float) dataChartList.get(i).getOpen());
}*/
/*values.add(new Entry(i, (float) dataChartList.get(i).getOpen()));
}*/

View File

@ -1,12 +1,11 @@
package com.nauk.coinfolio.Activities;
package com.herbron.moodl.Activities;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@ -15,25 +14,35 @@ import android.view.animation.Transformation;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
import com.nauk.coinfolio.DataManagers.BalanceManager;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyDetailsList;
import com.nauk.coinfolio.DataManagers.DatabaseManager;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.LayoutManagers.CurrencyListAdapter;
import com.nauk.coinfolio.R;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CoinmarketCapAPIManager;
import com.herbron.moodl.DataNotifiers.CoinmarketcapNotifierInterface;
import com.herbron.moodl.DataNotifiers.CryptocompareNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.CustomAdapters.CoinWatchlistAdapter;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
public class CurrencySelectionActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{
public class CurrencyListActivity extends AppCompatActivity implements SearchView.OnQueryTextListener, CryptocompareNotifierInterface, CoinmarketcapNotifierInterface {
private CurrencyListAdapter adapter;
private CoinWatchlistAdapter adapter;
private ListView listView;
private android.widget.Filter filter;
private CurrencyDetailsList currencyDetailsList;
private boolean isWatchList;
private CryptocompareApiManager cryptocompareApiManager;
private CoinmarketCapAPIManager coinmarketCapAPIManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -42,14 +51,15 @@ public class CurrencySelectionActivity extends AppCompatActivity implements Sear
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_add_currency);
setContentView(R.layout.activity_currency_list);
currencyDetailsList = new CurrencyDetailsList(this);
cryptocompareApiManager = CryptocompareApiManager.getInstance(this);
cryptocompareApiManager.addListener(this);
setTitle("Select a coin");
coinmarketCapAPIManager = CoinmarketCapAPIManager.getInstance(this);
coinmarketCapAPIManager.addListener(this);
Intent intent = getIntent();
isWatchList = intent.getBooleanExtra("isWatchList", false);
setTitle(getString(R.string.select_coin));
ListLoader listLoader = new ListLoader();
listLoader.execute();
@ -67,17 +77,7 @@ public class CurrencySelectionActivity extends AppCompatActivity implements Sear
private void setupAdapter()
{
List<String> currencyNames = currencyDetailsList.getCurrenciesName();
List<String> currencySymbols = currencyDetailsList.getCurrenciesSymbol();
ArrayList<Currency> currencyArrayList = new ArrayList<>();
for(int i = 0; i < currencyNames.size(); i++)
{
currencyArrayList.add(new Currency(currencyNames.get(i), currencySymbols.get(i)));
}
adapter = new CurrencyListAdapter(this, currencyArrayList);
adapter = new CoinWatchlistAdapter(this, new ArrayList<>(coinmarketCapAPIManager.getTotalListing()));
}
private void setupList()
@ -92,20 +92,16 @@ public class CurrencySelectionActivity extends AppCompatActivity implements Sear
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Currency selectedCurrency = (Currency) adapterView.getItemAtPosition(i);
if(isWatchList)
{
PreferencesManager preferencesManager = new PreferencesManager(getApplicationContext());
DatabaseManager databaseManager = new DatabaseManager(getApplicationContext());
PreferencesManager preferencesManager = new PreferencesManager(getApplicationContext());
DatabaseManager databaseManager = new DatabaseManager(getApplicationContext());
databaseManager.addCurrencyToWatchlist(selectedCurrency);
if(databaseManager.addCurrencyToWatchlist(selectedCurrency))
{
preferencesManager.setMustUpdateWatchlist(true);
}
else
{
Intent intent = new Intent(CurrencySelectionActivity.this, RecordTransactionActivity.class);
intent.putExtra("coin", selectedCurrency.getName());
intent.putExtra("symbol", selectedCurrency.getSymbol());
startActivity(intent);
Toast.makeText(getApplicationContext(), getString(R.string.already_watchlist), Toast.LENGTH_SHORT).show();
}
finish();
@ -146,14 +142,9 @@ public class CurrencySelectionActivity extends AppCompatActivity implements Sear
@Override
public boolean onQueryTextChange(String text)
{
filter.filter(text);
adapter.getFilter().filter(text);
if (TextUtils.isEmpty(text)) {
listView.clearTextFilter();
} else {
listView.setFilterText(text);
}
return true;
return false;
}
@Override
@ -162,6 +153,54 @@ public class CurrencySelectionActivity extends AppCompatActivity implements Sear
return false;
}
private void detailsEvent()
{
if(coinmarketCapAPIManager.isUpToDate() && cryptocompareApiManager.isDetailsUpToDate())
{
runOnUiThread(new Runnable() {
@Override
public void run() {
setupAdapter();
setupList();
setupSearchView();
expand(findViewById(R.id.listContainerLayout));
findViewById(R.id.currencyListProgressBar).setVisibility(View.GONE);
}
});
}
}
@Override
public void onDetailsUpdated() {
detailsEvent();
}
@Override
public void onExchangesUpdated() {
}
@Override
public void onCurrenciesRetrieved(List<Currency> currencyList) {
}
@Override
public void onTopCurrenciesUpdated() {
}
@Override
public void onMarketCapUpdated() {
}
@Override
public void onListingUpdated() {
detailsEvent();
}
private class ListLoader extends AsyncTask<Void, Integer, Void>
{
@Override
@ -184,24 +223,22 @@ public class CurrencySelectionActivity extends AppCompatActivity implements Sear
Looper.prepare();
}
currencyDetailsList.update(new BalanceManager.IconCallBack() {
@Override
public void onSuccess() {
setupAdapter();
setupList();
runOnUiThread(new Runnable() {
@Override
public void run() {
setupSearchView();
expand(findViewById(R.id.listContainerLayout));
findViewById(R.id.currencyListProgressBar).setVisibility(View.GONE);
}
});
if(!cryptocompareApiManager.isDetailsUpToDate() || !coinmarketCapAPIManager.isUpToDate())
{
if(!cryptocompareApiManager.isDetailsUpToDate())
{
cryptocompareApiManager.updateDetails();
}
});
if(!coinmarketCapAPIManager.isUpToDate())
{
coinmarketCapAPIManager.updateListing();
}
}
else
{
detailsEvent();
}
return null;
}

View File

@ -0,0 +1,666 @@
package com.herbron.moodl.Activities.DetailsActivityFragments;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.CandleStickChart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.CandleData;
import com.github.mikephil.charting.data.CandleDataSet;
import com.github.mikephil.charting.data.CandleEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.herbron.moodl.CurrencyInfoUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.CurrencyDataChart;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.CustomLayouts.CustomViewPager;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.List;
import static com.herbron.moodl.MoodlBox.getDateFromTimestamp;
import static com.herbron.moodl.MoodlBox.numberConformer;
/**
* Created by Tiji on 13/05/2018.
*/
public class ChartsFragment extends Fragment implements CurrencyInfoUpdateNotifierInterface {
private final static int HOUR = 0;
private final static int DAY = 1;
private final static int WEEK = 2;
private final static int MONTH = 3;
private final static int YEAR = 4;
private View view;
private Currency currency;
private LineChart lineChart;
private CandleStickChart candleStickChart;
private BarChart barChart;
private List<CurrencyDataChart> dataChartList;
private PreferencesManager preferencesManager;
private boolean displayLineChart;
private Button lineChartButton;
private Button candleStickChartButton;
private Spinner timeIntervalSpinner;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.detailsactivity_fragment_charts, container, false);
currency = getActivity().getIntent().getParcelableExtra("currency");
currency.setListener(this);
lineChart = view.findViewById(R.id.chartPriceView);
candleStickChart = view.findViewById(R.id.chartCandleStickView);
lineChartButton = view.findViewById(R.id.lineChartButton);
candleStickChartButton = view.findViewById(R.id.candleStickChartButton);
barChart = view.findViewById(R.id.chartVolumeView);
preferencesManager = new PreferencesManager(getActivity().getBaseContext());
displayLineChart = true;
lineChartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
lineChartButton.setEnabled(false);
candleStickChartButton.setEnabled(true);
lineChart.setVisibility(View.VISIBLE);
candleStickChart.setVisibility(View.GONE);
displayLineChart = true;
}
});
candleStickChartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
lineChartButton.setEnabled(true);
candleStickChartButton.setEnabled(false);
lineChart.setVisibility(View.GONE);
candleStickChart.setVisibility(View.VISIBLE);
displayLineChart = false;
}
});
initializeLineChart(lineChart);
initializeCandleStickChart(candleStickChart);
initializeSpinners();
return view;
}
private void initializeSpinners()
{
timeIntervalSpinner = view.findViewById(R.id.timeIntervalSinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity().getBaseContext(),
R.array.time_interval_string_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
timeIntervalSpinner.setAdapter(adapter);
timeIntervalSpinner.setSelection(2);
timeIntervalSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
updateCharts(i);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
private void updateCharts(int index)
{
view.findViewById(R.id.chartPriceView).setVisibility(View.GONE);
view.findViewById(R.id.chartCandleStickView).setVisibility(View.GONE);
view.findViewById(R.id.chartVolumeView).setVisibility(View.GONE);
view.findViewById(R.id.progressLayoutChart).setVisibility(View.VISIBLE);
switch (index)
{
case 0:
currency.updateHistoryMinutes(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 1:
currency.updateHistoryMinutes(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 2:
currency.updateHistoryMinutes(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 3:
currency.updateHistoryHours(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 4:
currency.updateHistoryHours(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 5:
currency.updateHistoryHours(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 6:
currency.updateHistoryDays(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 7:
currency.updateHistoryDays(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
case 8:
currency.updateHistoryDays(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency());
break;
}
}
private void initializeCandleStickChart(CandleStickChart candleStickChart)
{
candleStickChart.setDrawGridBackground(false);
candleStickChart.setDrawBorders(false);
candleStickChart.setDrawMarkers(true);
candleStickChart.getDescription().setEnabled(false);
candleStickChart.getAxisLeft().setEnabled(true);
candleStickChart.getAxisRight().setEnabled(true);
candleStickChart.getLegend().setEnabled(false);
candleStickChart.getXAxis().setEnabled(true);
candleStickChart.setViewPortOffsets(0, 0, 0, 0);
}
private void initializeLineChart(LineChart lineChart)
{
lineChart.setDrawGridBackground(false);
lineChart.setDrawBorders(false);
lineChart.setDrawMarkers(true);
lineChart.setDoubleTapToZoomEnabled(true);
lineChart.setPinchZoom(true);
lineChart.setScaleEnabled(false);
lineChart.setDragEnabled(true);
lineChart.getDescription().setEnabled(false);
lineChart.getAxisLeft().setEnabled(false);
lineChart.getAxisRight().setEnabled(false);
lineChart.getLegend().setEnabled(false);
lineChart.getXAxis().setEnabled(false);
lineChart.setViewPortOffsets(0, 0, 0, 0);
lineChart.setNoDataTextColor(currency.getChartColor());
}
private void updateChartTab(int timeUnit, int amount)
{
updateChartsData(timeUnit, amount);
if(currency.getHistoryMinutes() != null)
{
drawPriceLineChart();
drawPriceCandleStickChart();
drawVolumeChart();
updateGeneralData(lineChart.getData().getDataSets().get(0).getEntryForIndex(0).getY(), lineChart.getData().getDataSets().get(0).getEntryForIndex(lineChart.getData().getDataSets().get(0).getEntryCount() - 1).getY());
}
if(displayLineChart)
{
view.findViewById(R.id.chartPriceView).setVisibility(View.VISIBLE);
view.findViewById(R.id.progressLayoutChart).setVisibility(View.GONE);
}
else
{
view.findViewById(R.id.chartCandleStickView).setVisibility(View.VISIBLE);
view.findViewById(R.id.progressLayoutChart).setVisibility(View.GONE);
}
}
private void updateGeneralData(float start, float end)
{
double totalVolume = dataChartList.get(0).getVolumeTo();
double highestPrice = dataChartList.get(0).getOpen();
double lowestPrice = dataChartList.get(0).getOpen();
updateFluctuation(start, end);
((TextView) view.findViewById(R.id.txtViewPriceStart)).setText(PlaceholderUtils.getValueString(numberConformer(start), getActivity().getBaseContext()));
((TextView) view.findViewById(R.id.txtViewPriceNow)).setText(PlaceholderUtils.getValueString(numberConformer(end), getActivity().getBaseContext()));
for(int i = 1; i < dataChartList.size(); i++)
{
totalVolume += dataChartList.get(i).getVolumeTo();
if(highestPrice < dataChartList.get(i).getOpen())
{
highestPrice = dataChartList.get(i).getOpen();
}
if(lowestPrice > dataChartList.get(i).getOpen())
{
lowestPrice = dataChartList.get(i).getOpen();
}
}
((TextView) view.findViewById(R.id.totalVolume)).setText(PlaceholderUtils.getValueString(numberConformer(totalVolume), getActivity().getBaseContext()));
((TextView) view.findViewById(R.id.highestPrice)).setText(PlaceholderUtils.getValueString(numberConformer(highestPrice), getActivity().getBaseContext()));
((TextView) view.findViewById(R.id.lowestPrice)).setText(PlaceholderUtils.getValueString(numberConformer(lowestPrice), getActivity().getBaseContext()));
}
private void updateFluctuation(float start, float end)
{
float fluctuation = end - start;
float percentageFluctuation = (fluctuation / start * 100);
if(percentageFluctuation < 0)
{
((TextView) view.findViewById(R.id.txtViewPercentage)).setTextColor(getResources().getColor(R.color.red));
}
else
{
((TextView) view.findViewById(R.id.txtViewPercentage)).setTextColor(getResources().getColor(R.color.green));
}
((TextView) view.findViewById(R.id.txtViewPercentage)).setText(getResources().getString(R.string.currencyPercentagePlaceholder, numberConformer(percentageFluctuation)));
}
private void drawVolumeChart()
{
initializeBarChart(barChart);
barChart.setData(generateVolumeChartSet());
barChart.animateY(1000);
barChart.invalidate();
view.findViewById(R.id.chartVolumeView).setVisibility(View.VISIBLE);
}
private BarData generateVolumeChartSet()
{
BarDataSet dataSet;
ArrayList<BarEntry> values = new ArrayList<>();
int offset = (int) Math.floor(dataChartList.size() / 200);
if(offset < 1)
{
offset = 1;
}
for(int i = 0, j = 0; i < dataChartList.size(); i += offset, j++)
{
values.add(new BarEntry(j, (float) dataChartList.get(j).getVolumeTo()));
}
dataSet = new BarDataSet(values, "Volume");
dataSet.setDrawIcons(false);
dataSet.setColor(Color.GRAY);
dataSet.setDrawValues(false);
dataSet.setHighlightEnabled(true);
dataSet.setHighLightColor(currency.getChartColor());
return new BarData(dataSet);
}
private void initializeBarChart(BarChart barChart)
{
barChart.setDrawGridBackground(false);
barChart.setDrawBorders(false);
barChart.setDrawMarkers(true);
barChart.setDoubleTapToZoomEnabled(true);
barChart.setPinchZoom(true);
barChart.setScaleEnabled(false);
barChart.setDragEnabled(true);
barChart.getDescription().setEnabled(false);
barChart.getAxisLeft().setEnabled(false);
barChart.getAxisRight().setEnabled(false);
barChart.getLegend().setEnabled(false);
barChart.getXAxis().setEnabled(false);
barChart.setViewPortOffsets(0, 0, 0, 0);
barChart.setFitBars(true);
barChart.setHighlightFullBarEnabled(true);
barChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
barChartValueSelected(e);
}
@Override
public void onNothingSelected() {
}
});
barChart.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
return toucheEvent(motionEvent);
}
});
}
private void barChartValueSelected(Entry e)
{
int index = barChart.getData().getDataSets().get(0).getEntryIndex((BarEntry) e);
lineChart.highlightValue(lineChart.getData().getDataSets().get(0).getEntryForIndex(index).getX(), lineChart.getData().getDataSets().get(0).getEntryForIndex(index).getY(), 0);
generatePlaceHoldersFromIndex(index);
}
private boolean toucheEvent(MotionEvent motionEvent)
{
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
((CustomViewPager) view.getParent()).setPagingEnabled(false);
break;
case MotionEvent.ACTION_UP:
((CustomViewPager) view.getParent()).setPagingEnabled(true);
lineChart.highlightValue(null);
updateFluctuation(lineChart.getData().getDataSets().get(0).getEntryForIndex(0).getY(), lineChart.getData().getDataSets().get(0).getEntryForIndex(lineChart.getData().getDataSets().get(0).getEntryCount() - 1).getY());
barChart.highlightValues(null);
hideDataIndicators();
break;
}
return false;
}
private void hideDataIndicators()
{
((TextView) view.findViewById(R.id.volumeHightlight)).setText(".\n.");
view.findViewById(R.id.volumeHightlight).setVisibility(View.INVISIBLE);
((TextView) view.findViewById(R.id.priceHightlight)).setText(".\n.");
view.findViewById(R.id.priceHightlight).setVisibility(View.INVISIBLE);
((TextView) view.findViewById(R.id.timestampHightlight)).setText(".\n.");
view.findViewById(R.id.timestampHightlight).setVisibility(View.INVISIBLE);
}
private void drawPriceLineChart()
{
lineChart.setData(generatePriceLineChartSet());
lineChart.getAxisLeft().setAxisMinValue(lineChart.getData().getYMin());
lineChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
lineChartValueSelected(e);
}
@Override
public void onNothingSelected() {
}
});
lineChart.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
return toucheEvent(motionEvent);
}
});
}
private void lineChartValueSelected(Entry e)
{
int index = lineChart.getData().getDataSets().get(0).getEntryIndex(e);
barChart.highlightValue(barChart.getData().getDataSets().get(0).getEntryForIndex(index).getX(), 0, index);
generatePlaceHoldersFromIndex(index);
}
private void generatePlaceHoldersFromIndex(int index)
{
String date;
String volumePlaceholder;
String pricePlaceholder;
String timestampPlaceholder;
if(dataChartList.size() > 200)
{
date = getDateFromTimestamp(dataChartList.get((int) Math.floor(dataChartList.size() / 200) * index).getTimestamp() * 1000);
}
else
{
date = getDateFromTimestamp(dataChartList.get(index).getTimestamp() * 1000);
}
volumePlaceholder = PlaceholderUtils.getVolumeString(numberConformer(barChart.getData().getDataSets().get(0).getEntryForIndex(index).getY()), getActivity().getBaseContext());
pricePlaceholder = PlaceholderUtils.getPriceString(numberConformer((lineChart.getHighlighted())[0].getY()), getActivity().getBaseContext());
timestampPlaceholder = PlaceholderUtils.getTimestampString(date, getActivity().getBaseContext());
((TextView) view.findViewById(R.id.volumeHightlight)).setText(volumePlaceholder);
view.findViewById(R.id.volumeHightlight).setVisibility(View.VISIBLE);
((TextView) view.findViewById(R.id.priceHightlight)).setText(pricePlaceholder);
view.findViewById(R.id.priceHightlight).setVisibility(View.VISIBLE);
((TextView) view.findViewById(R.id.timestampHightlight)).setText(timestampPlaceholder);
view.findViewById(R.id.timestampHightlight).setVisibility(View.VISIBLE);
}
private LineData generatePriceLineChartSet()
{
LineDataSet dataSet;
ArrayList<Entry> values = new ArrayList<>();
int offsetRange = (int) Math.floor(dataChartList.size() / 200);
if(offsetRange < 1)
{
offsetRange = 1;
}
for(int i = 0, j = 0; i < dataChartList.size(); i += offsetRange, j++)
{
values.add(new Entry(j, (float) dataChartList.get(i).getOpen()));
}
dataSet = new LineDataSet(values, "History");
dataSet.setDrawIcons(false);
dataSet.setColor(currency.getChartColor());
dataSet.setLineWidth(1);
dataSet.setDrawFilled(true);
dataSet.setFillColor(getColorWithAlpha(currency.getChartColor(), 0.5f));
dataSet.setFormLineWidth(1);
dataSet.setFormSize(15);
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setHighlightEnabled(true);
dataSet.setDrawHorizontalHighlightIndicator(false);
dataSet.setHighLightColor(currency.getChartColor());
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
return new LineData(dataSet);
}
private int getColorWithAlpha(int color, float ratio)
{
int transColor;
int alpha = Math.round(Color.alpha(color) * ratio);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
transColor = Color.argb(alpha, r, g, b);
return transColor;
}
private void drawPriceCandleStickChart()
{
candleStickChart.setData(generatePriceCandleStickChartSet());
}
private CandleData generatePriceCandleStickChartSet()
{
CandleDataSet dataSet;
ArrayList<CandleEntry> values = new ArrayList<>();
int offsetRange = (int) Math.floor(dataChartList.size() / 200);
if(offsetRange < 1)
{
offsetRange = 1;
}
for(int i = 0, j = 0; i < dataChartList.size(); i+= offsetRange, j++)
{
values.add(new CandleEntry(j, (float) dataChartList.get(i).getHigh()
, (float) dataChartList.get(i).getLow()
, (float) dataChartList.get(i).getOpen()
, (float) dataChartList.get(i).getClose()));
}
dataSet = new CandleDataSet(values, "");
dataSet.setDrawIcons(false);
dataSet.setDrawValues(false);
dataSet.setDecreasingColor(MoodlBox.getColor(R.color.decreaseCandle, getActivity().getBaseContext()));
dataSet.setShowCandleBar(true);
dataSet.setShadowColorSameAsCandle(true);
dataSet.setDecreasingPaintStyle(Paint.Style.FILL);
dataSet.setIncreasingColor(MoodlBox.getColor(R.color.increaseCandle, getActivity().getBaseContext()));
dataSet.setIncreasingPaintStyle(Paint.Style.STROKE);
dataSet.setNeutralColor(MoodlBox.getColor(R.color.increaseCandle, getActivity().getBaseContext()));
dataSet.setHighLightColor(MoodlBox.getColor(R.color.colorAccent, getActivity().getBaseContext()));
dataSet.setDrawHorizontalHighlightIndicator(false);
return new CandleData(dataSet);
}
private void updateChartsData(int timeUnit, int amount)
{
dataChartList = null;
switch (timeUnit)
{
case HOUR:
if(currency.getHistoryMinutes() != null)
{
dataChartList = currency.getHistoryMinutes().subList(currency.getHistoryMinutes().size()-(60*amount), currency.getHistoryMinutes().size());
}
break;
case DAY:
if(amount == 1)
{
dataChartList = currency.getHistoryMinutes();
}
else
{
if(currency.getHistoryHours() != null)
{
dataChartList = currency.getHistoryHours().subList(currency.getHistoryHours().size()-(24*amount), currency.getHistoryHours().size());
}
}
break;
case WEEK:
if(currency.getHistoryHours() != null)
{
dataChartList = currency.getHistoryHours().subList(currency.getHistoryHours().size()-168, currency.getHistoryHours().size());
}
break;
case MONTH:
switch (amount)
{
case 1:
dataChartList = currency.getHistoryHours();
break;
case 3:
if(currency.getHistoryDays() != null)
{
dataChartList = currency.getHistoryDays().subList(currency.getHistoryDays().size()-93, currency.getHistoryDays().size());
}
break;
case 6:
if(currency.getHistoryDays() != null)
{
dataChartList = currency.getHistoryDays().subList(currency.getHistoryDays().size()-186, currency.getHistoryDays().size());
}
break;
}
break;
case YEAR:
dataChartList = currency.getHistoryDays();
break;
}
}
@Override
public void onTimestampPriceUpdated(String price) {
}
@Override
public void onHistoryDataUpdated() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
switch (timeIntervalSpinner.getSelectedItemPosition())
{
case 0:
updateChartTab(ChartsFragment.HOUR, 1);
break;
case 1:
updateChartTab(ChartsFragment.HOUR, 3);
break;
case 2:
updateChartTab(ChartsFragment.DAY, 1);
break;
case 3:
updateChartTab(ChartsFragment.DAY, 3);
break;
case 4:
updateChartTab(ChartsFragment.WEEK, 11);
break;
case 5:
updateChartTab(ChartsFragment.MONTH, 1);
break;
case 6:
updateChartTab(ChartsFragment.MONTH, 3);
break;
case 7:
updateChartTab(ChartsFragment.MONTH, 6);
break;
case 8:
updateChartTab(ChartsFragment.YEAR, 1);
break;
}
}
});
}
@Override
public void onPriceUpdated(Currency currency) {
}
}

View File

@ -0,0 +1,158 @@
package com.herbron.moodl.Activities.DetailsActivityFragments;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import static com.herbron.moodl.MoodlBox.numberConformer;
/**
* Created by Tiji on 13/05/2018.
*/
public class InformationFragment extends Fragment {
private Currency currency;
private View view;
private PreferencesManager preferencesManager;
private boolean isSnapshotUpdated;
private boolean isTickerUpdated;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.detailsactivity_fragment_informations, container, false);
isSnapshotUpdated = false;
isTickerUpdated = false;
currency = getActivity().getIntent().getParcelableExtra("currency");
preferencesManager = new PreferencesManager(getActivity().getBaseContext());
updateInfoTab();
return view;
}
private void updateInfoTab()
{
currency.updateSnapshot(getActivity().getBaseContext(), new Currency.CurrencyCallBack() {
@Override
public void onSuccess(final Currency currency) {
isSnapshotUpdated = true;
dataCounter();
}
});
currency.updateTicker(getActivity().getBaseContext(), preferencesManager.getDefaultCurrency(), new Currency.CurrencyCallBack() {
@Override
public void onSuccess(Currency currency) {
isTickerUpdated = true;
dataCounter();
}
});
}
private void dataCounter()
{
if(isTickerUpdated && isSnapshotUpdated)
{
try {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
refreshInfoTab();
}
});
} catch (NullPointerException e) {
Log.d("moodl", "Information tab do not needs to be updated anymore");
}
}
}
private void refreshInfoTab()
{
Drawable progressBarDrawable = ((ProgressBar) view.findViewById(R.id.percentageCoinEmited)).getProgressDrawable();
progressBarDrawable.mutate();
progressBarDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
progressBarDrawable.invalidateSelf();
((ProgressBar) view.findViewById(R.id.percentageCoinEmited))
.setProgress((int) Math.round(currency.getMinedCoinSupply() / currency.getMaxCoinSupply() * 100));
if(currency.getAlgorithm() != null && !currency.getAlgorithm().equals(""))
{
((TextView) view.findViewById(R.id.txtViewAlgorithm))
.setText(currency.getAlgorithm());
}
if(currency.getProofType() != null && !currency.getProofType().equals(""))
{
((TextView) view.findViewById(R.id.txtViewProofType))
.setText(currency.getProofType());
}
if(currency.getStartDate() != null && !currency.getStartDate().equals(""))
{
((TextView) view.findViewById(R.id.txtViewStartDate))
.setText(currency.getStartDate());
}
if(currency.getDescription() != null)
{
((TextView) view.findViewById(R.id.txtViewDescription))
.setText(Html.fromHtml(currency.getDescription()));
}
((TextView) view.findViewById(R.id.txtViewDescription))
.setMovementMethod(LinkMovementMethod.getInstance());
((TextView) view.findViewById(R.id.txtViewPercentageCoinEmited))
.setText(PlaceholderUtils.getEmitedPercentageString(numberConformer(currency.getMinedCoinSupply() / currency.getMaxCoinSupply() * 100), getActivity().getBaseContext()));
if(currency.getMarketCapitalization() != 0)
{
((TextView) view.findViewById(R.id.txtViewMarketCapitalization))
.setText(PlaceholderUtils.getValueString(numberConformer(currency.getMarketCapitalization()), getActivity().getBaseContext()));
view.findViewById(R.id.linearMarketCap).setVisibility(View.VISIBLE);
}
if(currency.getRank() != 0)
{
((TextView) view.findViewById(R.id.txtViewRank))
.setText(String.valueOf(currency.getRank()));
view.findViewById(R.id.linearRank).setVisibility(View.VISIBLE);
}
if(currency.getMaxCoinSupply() == 0)
{
((TextView) view.findViewById(R.id.txtViewTotalSupply))
.setText(PlaceholderUtils.getSymbolString(getString(R.string.infinity), getActivity()));
}
else
{
((TextView) view.findViewById(R.id.txtViewTotalSupply))
.setText(PlaceholderUtils.getSymbolString(numberConformer(currency.getMaxCoinSupply()), getActivity()));
}
((TextView) view.findViewById(R.id.txtViewCirculatingSupply))
.setText(PlaceholderUtils.getSymbolString(numberConformer(currency.getMinedCoinSupply()), getActivity()));
}
}

View File

@ -0,0 +1,395 @@
package com.herbron.moodl.Activities.DetailsActivityFragments;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.herbron.moodl.DataNotifiers.BinanceUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Trade;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.ExchangeManager.BinanceManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.CustomAdapters.TransactionListAdapter;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created by Tiji on 13/05/2018.
*/
public class TransactionsFragment extends Fragment {
private Currency currency;
private View loadingFooter;
private View view;
//private ListView tradeLayout;
private ListView transactionLayout;
private boolean flag_loading;
private List<BinanceManager> binanceManagerList;
private DatabaseManager databaseManager;
private ArrayList<com.herbron.moodl.DataManagers.CurrencyData.Trade> returnedTrades;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.detailsactivity_fragment_transactions, container, false);
PreferencesManager preferencesManager = new PreferencesManager(getActivity().getBaseContext());
currency = getActivity().getIntent().getParcelableExtra("currency");
databaseManager = new DatabaseManager(getActivity().getBaseContext());
binanceManagerList = databaseManager.getBinanceAccounts();
//tradeLayout = view.findViewById(R.id.listTrades);
transactionLayout = view.findViewById(R.id.listTransactions);
flag_loading = false;
TransactionUpdater transactionUpdater = new TransactionUpdater();
transactionUpdater.execute();
return view;
}
private class TransactionUpdater extends AsyncTask<Void, Integer, Void> implements BinanceUpdateNotifierInterface
{
private ArrayList<Object> displayedTransactions;
private int nbTradeAccountUpdated;
private int nbTransactionAccountUpdated;
@Override
protected void onPreExecute() {
super.onPreExecute();
displayedTransactions = new ArrayList<>();
nbTradeAccountUpdated = 0;
nbTransactionAccountUpdated = 0;
}
@Override
protected Void doInBackground(Void... voids) {
if(Looper.myLooper() == null)
{
Looper.prepare();
}
displayedTransactions.addAll(databaseManager.getCurrencyTransactionsForSymbol(currency.getSymbol()));
for(int i = 0; i < binanceManagerList.size(); i++)
{
binanceManagerList.get(i).addListener(this);
binanceManagerList.get(i).updateTrades(currency.getSymbol());
binanceManagerList.get(i).updateTransactions(currency.getSymbol());
}
if(nbTradeAccountUpdated == binanceManagerList.size())
{
drawTransactionList(displayedTransactions);
}
return null;
}
@Override
public void onBinanceTradesUpdated(List<Trade> trades) {
nbTradeAccountUpdated++;
displayedTransactions.addAll(trades);
if(nbTradeAccountUpdated == binanceManagerList.size())
{
drawTransactionList(displayedTransactions);
}
}
@Override
public void onBinanceBalanceUpdateSuccess() {
}
@Override
public void onBinanceBalanceUpdateError(int accountId, String error) {
}
private void drawTransactionList(ArrayList<Object> transactions)
{
Collections.sort(transactions, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
Long time1;
Long time2;
if(o1 instanceof Transaction)
{
time1 = ((Transaction) o1).getTimestamp();
}
else
{
time1 = ((Trade) o1).getTime();
}
if(o2 instanceof Transaction)
{
time2 = ((Transaction) o2).getTimestamp();
}
else
{
time2 = ((Trade) o2).getTime();
}
return time2.compareTo(time1);
}
});
if(getActivity() != null)
{
TransactionListAdapter transactionListAdapter = new TransactionListAdapter(getActivity(), transactions);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
transactionLayout.setAdapter(transactionListAdapter);
transactionLayout.setTextFilterEnabled(false);
}
});
}
}
}
/*public class TransactionUpdater extends AsyncTask<Void, Integer, Void>
{
@Override
protected Void doInBackground(Void... voids) {
if(Looper.myLooper() == null)
{
Looper.prepare();
}
//binanceManager.updateTransactions(currency.getSymbol());
final ArrayList<Transaction> transactionList = databaseManager.getCurrencyTransactionsForSymbol(currency.getSymbol());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
drawTransactionList(transactionList);
}
});
return null;
}
}*/
/*private class TradeAdder extends AsyncTask<Void, Integer, Void>
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
loadingIndicatorGenerator();
}
@Override
protected Void doInBackground(Void... voids) {
final ArrayList<Trade> trades = new ArrayList<>();
for(int i = tradeLayout.getCount(); i < tradeLayout.getCount() + 20 && i < returnedTrades.size(); i++)
{
trades.add(returnedTrades.get(i));
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
tradeListAdapter.addAll(trades);
tradeListAdapter.notifyDataSetChanged();
flag_loading = false;
tradeLayout.removeFooterView(loadingFooter);
}
});
binanceManager.updateTrades(new BinanceManager.BinanceCallBack() {
@Override
public void onSuccess() {
ArrayList<com.nauk.moodl.DataManagers.CurrencyData.Trade> trades = binanceManager.getTrades();
final ArrayList<com.nauk.moodl.DataManagers.CurrencyData.Trade> returnedTrades = new ArrayList<>();
for(int i = trades.size() - 1; i > 0 ; i--)
{
returnedTrades.add(trades.get(i));
}
runOnUiThread(new Runnable() {
@Override
public void run() {
tradeListAdapter.addAll(returnedTrades);
tradeListAdapter.notifyDataSetChanged();
flag_loading = false;
tradeLayout.removeFooterView(loadingFooter);
}
});
}
@Override
public void onError(String error) {
}
}, currency.getSymbol(), tradeListAdapter.getItem(tradeListAdapter.getCount() - 1).getId());
return null;
}
}*/
/*private void drawTransactionList(ArrayList<Transaction> transactions)
{
TransactionListAdapter transactionListAdapter = new TransactionListAdapter(getActivity(), transactions);
transactionLayout.setAdapter(transactionListAdapter);
transactionLayout.setTextFilterEnabled(false);
}
private class TradeUpdater extends AsyncTask<Void, Integer, Void> implements BinanceUpdateNotifierInterface
{
private List<Trade> trades;
private int nbResponse;
@Override
protected void onPreExecute()
{
super.onPreExecute();
trades = new ArrayList<>();
nbResponse = 0;
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
}
@Override
protected Void doInBackground(Void... params)
{
for(int i = 0; i < binanceManagerList.size(); i++)
{
binanceManagerList.get(i).addListener(this);
binanceManagerList.get(i).updateTrades(currency.getSymbol());
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
}
@Override
public void onBinanceTradesUpdated(List<Trade> newTrades) {
trades.addAll(newTrades);
nbResponse++;
if(nbResponse == binanceManagerList.size())
{
returnedTrades = new ArrayList<>();
for(int i = trades.size() - 1; i >= 0 ; i--)
{
returnedTrades.add(trades.get(i));
}
try {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ArrayList<Trade> trades = new ArrayList<>();
for(int i = 0; i < 20 && i < returnedTrades.size(); i++)
{
trades.add(returnedTrades.get(i));
}
//drawTradeList(trades);
}
});
} catch (NullPointerException e) {
Log.d("moodl", "TransactionsFragment do not need to be updated anymore");
}
}
}
@Override
public void onBinanceBalanceUpdateSuccess() {
}
@Override
public void onBinanceBalanceUpdateError(int accountId, String error) {
}
}*/
/*private void loadingIndicatorGenerator()
{
loadingFooter = LayoutInflater.from(getActivity().getBaseContext()).inflate(R.layout.listview_loading_indicator, null, false);
Drawable drawable = ((ProgressBar) loadingFooter.findViewById(R.id.progressIndicator)).getIndeterminateDrawable();
drawable.mutate();
drawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
drawable.invalidateSelf();
tradeLayout.addFooterView(loadingFooter);
}
private void drawTradeList(ArrayList<com.herbron.moodl.DataManagers.CurrencyData.Trade> trades)
{
if(returnedTrades.size() > 20)
{
tradeLayout.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
{
if(!flag_loading && tradeLayout.getCount() != returnedTrades.size() - 1)
{
flag_loading = true;
TradeAdder tradeAdder = new TradeAdder();
tradeAdder.execute();
}
}
}
});
}
tradeListAdapter = new TradeListAdapter(getActivity().getBaseContext(), trades);
tradeLayout.setAdapter(tradeListAdapter);
tradeLayout.setTextFilterEnabled(false);
view.findViewById(R.id.tradeLoaderIndicator).setVisibility(View.GONE);
}*/
}

View File

@ -0,0 +1,66 @@
package com.herbron.moodl.Activities;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.CustomAdapters.ExchangeDescriptionListAdapter;
import com.herbron.moodl.R;
public class ExchangeListActivity extends AppCompatActivity {
private DatabaseManager databaseManager;
private ListView exchangeListView;
private ExchangeDescriptionListAdapter exchangeDescriptionListAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exchange_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
databaseManager = new DatabaseManager(this);
exchangeListView = findViewById(R.id.exchange_listView);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(ExchangeListActivity.this, AddExchangeActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onResume() {
super.onResume();
exchangeDescriptionListAdapter = new ExchangeDescriptionListAdapter(getApplicationContext(), databaseManager.getExchanges());
exchangeListView.setAdapter(exchangeDescriptionListAdapter);
exchangeDescriptionListAdapter.notifyDataSetChanged();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -0,0 +1,253 @@
package com.herbron.moodl.Activities;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import com.herbron.moodl.Activities.HomeActivityFragments.MarketCapitalization;
import com.herbron.moodl.Activities.HomeActivityFragments.Overview;
import com.herbron.moodl.Activities.HomeActivityFragments.Summary;
import com.herbron.moodl.Activities.HomeActivityFragments.Watchlist;
import com.herbron.moodl.BalanceSwitchManagerInterface;
import com.herbron.moodl.BalanceUpdateInterface;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import static com.herbron.moodl.MoodlBox.numberConformer;
//Use WilliamChart for charts https://github.com/diogobernardino/WilliamChart
//Auto refresh with predefined intervals
//Multiple portfolio (exchanges & custom)
//Add roadmap to buy a coin
//Add reddit link ?
//
public class HomeActivity extends AppCompatActivity implements BalanceUpdateInterface {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
private DrawerLayout drawerLayout;
private Fragment watchlistFragment;
private Fragment holdingsFragment;
private Fragment marketFragment;
private Fragment overviewFragment;
private Fragment currentFragment;
private DatabaseManager databaseManager;
private TextView alertTextView;
private BalanceSwitchManagerInterface switchInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStatusBarGradiant(this);
/**Interface setup**/
setContentView(R.layout.activity_currency_summary);
watchlistFragment = new Watchlist();
holdingsFragment = new Summary();
marketFragment = new MarketCapitalization();
overviewFragment = new Overview();
drawerLayout = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
databaseManager = new DatabaseManager(this);
setListener((BalanceSwitchManagerInterface) holdingsFragment);
showFragment(holdingsFragment);
navigationView.setCheckedItem(R.id.navigation_holdings);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
item.setChecked(true);
switch (item.getItemId())
{
case R.id.navigation_watchlist:
showFragment(watchlistFragment);
break;
case R.id.navigation_holdings:
showFragment(holdingsFragment);
break;
case R.id.navigation_market_cap:
showFragment(marketFragment);
break;
case R.id.navigation_overview:
showFragment(overviewFragment);
break;
case R.id.navigation_settings:
Intent settingIntent = new Intent(getApplicationContext(), SettingsActivity.class);
settingIntent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, SettingsActivity.MainPreferenceFragment.class.getName() );
settingIntent.putExtra(PreferenceActivity.EXTRA_NO_HEADERS, true );
startActivity(settingIntent);
item.setChecked(false);
break;
}
drawerLayout.closeDrawers();
return false;
}
});
setupSettingsAlert(navigationView);
setupBalanceSwitch();
}
private void setupSettingsAlert(NavigationView navigationView)
{
alertTextView = (TextView) navigationView.getMenu().findItem(R.id.navigation_settings).getActionView();
alertTextView.setTextColor(getResources().getColor(R.color.decreaseCandle));
alertTextView.setGravity(Gravity.CENTER);
alertTextView.setTypeface(null, Typeface.BOLD);
updateSettingsAlertNumber();
}
private void updateSettingsAlertNumber()
{
int disabledNumber = databaseManager.getDisabledExchangeAccountsNumber();
if(disabledNumber > 0)
{
alertTextView.setText(String.valueOf(disabledNumber));
}
else
{
alertTextView.setText("");
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setStatusBarGradiant(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
Drawable background = activity.getResources().getDrawable(R.drawable.gradient_background);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(android.R.color.transparent));
window.setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent));
window.setBackgroundDrawable(background);
}
}
@Override
public void onBackPressed() {
drawerLayout.openDrawer(GravityCompat.START);
}
public void setListener(BalanceSwitchManagerInterface switchInterface)
{
this.switchInterface = switchInterface;
}
private void setupBalanceSwitch()
{
Switch balanceSwitch = findViewById(R.id.switchHideBalance);
PreferencesManager preferencesManager = new PreferencesManager(getBaseContext());
balanceSwitch.setChecked(preferencesManager.isBalanceHidden());
balanceSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
switchInterface.buttonCheckedChange();
}
});
}
private void showFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if(currentFragment != null)
{
fragmentTransaction.hide(currentFragment);
}
if(fragment.isAdded())
{
fragmentTransaction.show(fragment);
}
else
{
fragmentTransaction.add(R.id.content_frame, fragment).addToBackStack(null);
}
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
currentFragment = fragment;
}
public Fragment getHoldingsFragment()
{
return holdingsFragment;
}
@Override
protected void onResume() {
super.onResume();
updateSettingsAlertNumber();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.menu_currency_summary, menu);
return true;
}
@Override
public void onBalanceUpdated(float value) {
PreferencesManager preferencesManager = new PreferencesManager(getApplicationContext());
NavigationView navigationView = findViewById(R.id.nav_view);
TextView drawerBalanceTextView = navigationView.getHeaderView(0).findViewById(R.id.balanceTextView);
if(preferencesManager.isBalanceHidden())
{
drawerBalanceTextView.setText(PlaceholderUtils.getPercentageString(numberConformer(value), getApplicationContext()));
}
else
{
drawerBalanceTextView.setText(PlaceholderUtils.getValueString(numberConformer(value), getApplicationContext()));
}
}
}

View File

@ -0,0 +1,440 @@
package com.herbron.moodl.Activities.HomeActivityFragments;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.NestedScrollView;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.graphics.Palette;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.formatter.PercentFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.herbron.moodl.DataNotifiers.CoinmarketcapNotifierInterface;
import com.herbron.moodl.DataNotifiers.CryptocompareNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CoinmarketCapAPIManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.CustomLayouts.CustomPieChart;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.List;
import static com.herbron.moodl.MoodlBox.getColor;
import static com.herbron.moodl.MoodlBox.getIconDominantColor;
import static java.lang.Math.abs;
/**
* Created by Tiji on 13/04/2018.
*/
public class MarketCapitalization extends Fragment implements CryptocompareNotifierInterface, CoinmarketcapNotifierInterface {
private PreferencesManager preferencesManager;
private CoinmarketCapAPIManager coinmarketCapAPIManager;
private SwipeRefreshLayout refreshLayout;
private NestedScrollView nestedScrollView;
private long lastTimestamp;
private String defaultCurrency;
private CryptocompareApiManager cryptocompareApiManager;
private boolean isDetailsUpdated;
private boolean isTopCurrenciesUpdated;
private boolean isMarketpCapUpdated;
private int iconCounter;
private View view;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.homeactivity_fragment_marketcap, container, false);
preferencesManager = new PreferencesManager(getActivity().getBaseContext());
coinmarketCapAPIManager = CoinmarketCapAPIManager.getInstance(getActivity().getBaseContext());
coinmarketCapAPIManager.addListener(this);
cryptocompareApiManager = CryptocompareApiManager.getInstance(getActivity().getBaseContext());
cryptocompareApiManager.addListener(this);
if(!cryptocompareApiManager.isDetailsUpToDate())
{
cryptocompareApiManager.updateDetails();
}
else
{
isDetailsUpdated = true;
countCompletedMarketCapRequest();
}
defaultCurrency = preferencesManager.getDefaultCurrency();
lastTimestamp = 0;
nestedScrollView = view.findViewById(R.id.nestedMarketCap);
setupRefreshLayout();
setupDrawerButton();
updateMarketCap(true);
return view;
}
private void setupDrawerButton()
{
ImageButton drawerButton = view.findViewById(R.id.drawer_button);
drawerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DrawerLayout drawerLayout = getActivity().findViewById(R.id.drawer_layout);
if(drawerLayout.isDrawerOpen(GravityCompat.START))
{
drawerLayout.closeDrawers();
}
else
{
drawerLayout.openDrawer(GravityCompat.START);
}
}
});
}
private void setupRefreshLayout()
{
refreshLayout = view.findViewById(R.id.swiperefreshmarketcap);
refreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateMarketCap(false);
}
}
);
}
@Override
public void onResume()
{
super.onResume();
if(!defaultCurrency.equals(preferencesManager.getDefaultCurrency()))
{
defaultCurrency = preferencesManager.getDefaultCurrency();
updateMarketCap(true);
}
else
{
updateMarketCap(false);
}
}
private void updateMarketCap(boolean mustUpdate)
{
if(System.currentTimeMillis() / 1000 - lastTimestamp > 60 || mustUpdate)
{
if(!refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(true);
}
iconCounter = 0;
isTopCurrenciesUpdated = false;
isMarketpCapUpdated = false;
lastTimestamp = System.currentTimeMillis() / 1000;
coinmarketCapAPIManager.updateTopCurrencies(preferencesManager.getDefaultCurrency());
coinmarketCapAPIManager.updateMarketCap(preferencesManager.getDefaultCurrency());
}
else
{
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
}
private void refreshDisplayedData()
{
view.findViewById(R.id.progressBarMarketCap).setVisibility(View.GONE);
view.findViewById(R.id.layoutProgressMarketCap).setVisibility(View.VISIBLE);
PieData data = new PieData(getMarketDominanceDataSet());
data.setValueTextSize(10);
data.setValueFormatter(new PercentFormatter());
setupPieChart(data);
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
private PieDataSet getMarketDominanceDataSet()
{
List<PieEntry> entries = new ArrayList<>();
List<Currency> topCurrencies = coinmarketCapAPIManager.getTopCurrencies();
ArrayList<Integer> colors = new ArrayList<>();
float topCurrenciesDominance = 0;
for(int i = 0; i < topCurrencies.size(); i++)
{
PieEntry pieEntry = new PieEntry(topCurrencies.get(i).getDominance(coinmarketCapAPIManager.getMarketCap()), topCurrencies.get(i).getSymbol(), topCurrencies.get(i).getSymbol());
if(pieEntry.getValue() < 3)
{
pieEntry.setLabel("");
}
entries.add(pieEntry);
topCurrenciesDominance += topCurrencies.get(i).getDominance(coinmarketCapAPIManager.getMarketCap());
colors.add(topCurrencies.get(i).getChartColor());
}
entries.add(new PieEntry(100-topCurrenciesDominance, getString(R.string.others), "others"));
colors.add(-12369084);
PieDataSet set = new PieDataSet(entries, getString(R.string.market_dominance));
set.setColors(colors);
set.setSliceSpace(1);
set.setDrawValues(false);
return set;
}
@SuppressLint("ClickableViewAccessibility")
private void countCompletedMarketCapRequest()
{
if(isTopCurrenciesUpdated && isMarketpCapUpdated && isDetailsUpdated)
{
updateIcons();
}
}
private void countIcons()
{
iconCounter++;
if(iconCounter >= coinmarketCapAPIManager.getTopCurrencies().size())
{
refreshDisplayedData();
}
}
private void updateIcons()
{
for(int i = 0; i < coinmarketCapAPIManager.getTopCurrencies().size(); i++)
{
final Currency localCurrency = coinmarketCapAPIManager.getTopCurrencies().get(i);
final int index = i;
String iconUrl = MoodlBox.getIconUrl(coinmarketCapAPIManager.getTopCurrencies().get(i).getSymbol(), 500, cryptocompareApiManager);
if(iconUrl != null)
{
MoodlBox.getBitmapFromURL(iconUrl, localCurrency.getSymbol(), getResources(), getActivity().getBaseContext(), new MoodlboxNotifierInterface() {
@Override
public void onBitmapDownloaded(Bitmap bitmapIcon) {
coinmarketCapAPIManager.getTopCurrencies().get(index).setIcon(bitmapIcon);
coinmarketCapAPIManager.getTopCurrencies().get(index).setChartColor(getIconDominantColor(getContext(), bitmapIcon));
countIcons();
}
});
}
else
{
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_moodl);
icon = Bitmap.createScaledBitmap(icon, 500, 500, false);
localCurrency.setIcon(icon);
countIcons();
}
}
}
private void setupPieChart(PieData data)
{
CustomPieChart pieChart = view.findViewById(R.id.marketCapPieChart);
pieChart.setData(data);
pieChart.setDrawSlicesUnderHole(false);
pieChart.setUsePercentValues(false);
pieChart.setTouchEnabled(true);
pieChart.setEntryLabelColor(Color.WHITE);
updateDetails(coinmarketCapAPIManager.getMarketCap(), coinmarketCapAPIManager.getDayVolume(), getString(R.string.global), 0);
((TextView) view.findViewById(R.id.textViewActiveCrypto))
.setText(coinmarketCapAPIManager.getActive_crypto());
((TextView) view.findViewById(R.id.textViewActiveMarkets))
.setText(coinmarketCapAPIManager.getActive_markets());
pieChart.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
nestedScrollView.setEnabled(false);
break;
case MotionEvent.ACTION_MOVE:
break;
default:
nestedScrollView.setEnabled(true);
break;
}
view.performClick();
return false;
}
});
pieChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
view.findViewById(R.id.layoutActiveCrypto).setVisibility(View.GONE);
view.findViewById(R.id.layoutActiveMarkets).setVisibility(View.GONE);
if(!e.getData().equals("others"))
{
Currency currency = coinmarketCapAPIManager.getCurrencyFromSymbol((String) e.getData());
view.findViewById(R.id.currencyIcon).setVisibility(View.VISIBLE);
view.findViewById(R.id.layoutPercentageDominance).setVisibility(View.VISIBLE);
updateDetails(currency.getMarketCapitalization(), currency.getVolume24h(), currency.getName() + " (" + currency.getSymbol() + ")", h.getY());
((ImageView) view.findViewById(R.id.currencyIcon))
.setImageBitmap(currency.getIcon());
pieChart.setDrawCenterText(false);
}
else
{
double othersMarketCap = coinmarketCapAPIManager.getMarketCap();
double othersVolume = coinmarketCapAPIManager.getDayVolume();
for(int i = 0; i < coinmarketCapAPIManager.getTopCurrencies().size(); i++)
{
othersMarketCap -= coinmarketCapAPIManager.getTopCurrencies().get(i).getMarketCapitalization();
othersVolume -= coinmarketCapAPIManager.getTopCurrencies().get(i).getVolume24h();
}
view.findViewById(R.id.currencyIcon).setVisibility(View.GONE);
view.findViewById(R.id.layoutPercentageDominance).setVisibility(View.VISIBLE);
updateDetails(othersMarketCap, othersVolume, getString(R.string.other_coins), h.getY());
pieChart.setDrawCenterText(true);
}
}
});
}
@Override
public void onNothingSelected() {
view.findViewById(R.id.currencyIcon).setVisibility(View.GONE);
view.findViewById(R.id.layoutPercentageDominance).setVisibility(View.GONE);
view.findViewById(R.id.layoutActiveCrypto).setVisibility(View.VISIBLE);
view.findViewById(R.id.layoutActiveMarkets).setVisibility(View.VISIBLE);
updateDetails(coinmarketCapAPIManager.getMarketCap(), coinmarketCapAPIManager.getDayVolume(), getString(R.string.global), 0);
pieChart.setDrawCenterText(true);
}
});
pieChart.getDescription().setEnabled(false);
pieChart.getLegend().setEnabled(false);
pieChart.setCenterText(generateCenterSpannableText());
pieChart.invalidate();
}
private void updateDetails(double marketCap, double volume, String title, double percentage)
{
((TextView) view.findViewById(R.id.textViewMarketCap))
.setText(PlaceholderUtils.getValueString(MoodlBox.numberConformer(marketCap), getActivity().getBaseContext()));
((TextView) view.findViewById(R.id.textViewVolume))
.setText(PlaceholderUtils.getValueString(MoodlBox.numberConformer(volume), getActivity().getBaseContext()));
((TextView) view.findViewById(R.id.textViewTitle))
.setText(title);
((TextView) view.findViewById(R.id.textViewDominancePercentage))
.setText(PlaceholderUtils.getPercentageString(MoodlBox.numberConformer(percentage), getActivity().getBaseContext()));
}
private SpannableString generateCenterSpannableText() {
SpannableString spannableString = new SpannableString(getString(R.string.market_dominance));
return spannableString;
}
@Override
public void onDetailsUpdated() {
isDetailsUpdated = true;
countCompletedMarketCapRequest();
}
@Override
public void onExchangesUpdated() {
}
@Override
public void onCurrenciesRetrieved(List<Currency> currencyList) {
}
@Override
public void onTopCurrenciesUpdated() {
isTopCurrenciesUpdated = true;
countCompletedMarketCapRequest();
}
@Override
public void onMarketCapUpdated() {
isMarketpCapUpdated = true;
countCompletedMarketCapRequest();
}
@Override
public void onListingUpdated() {
}
}

View File

@ -0,0 +1,245 @@
package com.herbron.moodl.Activities.HomeActivityFragments;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.graphics.Palette;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ImageButton;
import android.widget.ListView;
import com.herbron.moodl.DataNotifiers.CoinmarketcapNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CoinmarketCapAPIManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.CustomAdapters.OverviewListAdapter;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import com.herbron.moodl.R;
import java.util.List;
import static com.herbron.moodl.MoodlBox.getDrawable;
import static com.herbron.moodl.MoodlBox.getIconDominantColor;
/**
* Created by Administrator on 27/05/2018.
*/
public class Overview extends Fragment implements CoinmarketcapNotifierInterface {
private CoinmarketCapAPIManager coinmarketCapAPIManager;
private CryptocompareApiManager cryptocompareApiManager;
private PreferencesManager preferenceManager;
private OverviewListAdapter overviewListAdapter;
private View loadingFooter;
boolean flag_loading;
private ListView listLayout;
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View fragmentView = inflater.inflate(R.layout.homeactivity_fragment_overview, container, false);
coinmarketCapAPIManager = CoinmarketCapAPIManager.getInstance(getActivity().getBaseContext());
cryptocompareApiManager = CryptocompareApiManager.getInstance(getActivity().getBaseContext());
coinmarketCapAPIManager.addListener(this);
fragmentView.findViewById(R.id.toolbar).bringToFront();
preferenceManager = new PreferencesManager(getActivity().getBaseContext());
listLayout = fragmentView.findViewById(R.id.linearLayoutOverview);
listLayout.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount != 0)
{
if(!flag_loading)
{
flag_loading = true;
updateList();
}
}
}
});
flag_loading = true;
updateList();
setupDrawerButton(fragmentView);
return fragmentView;
}
private void setupDrawerButton(View view)
{
ImageButton drawerButton = view.findViewById(R.id.drawer_button);
drawerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DrawerLayout drawerLayout = getActivity().findViewById(R.id.drawer_layout);
if(drawerLayout.isDrawerOpen(GravityCompat.START))
{
drawerLayout.closeDrawers();
}
else
{
drawerLayout.openDrawer(GravityCompat.START);
}
}
});
}
private void updateList()
{
CurrencyLoader currencyLoader = new CurrencyLoader();
currencyLoader.execute();
}
private void loadingIndicatorGenerator()
{
loadingFooter = LayoutInflater.from(getActivity().getBaseContext()).inflate(R.layout.listview_loading_indicator, null, false);
listLayout.addFooterView(loadingFooter);
}
@Override
public void onCurrenciesRetrieved(List<Currency> currencyList) {
IconDownloader iconDownloader = new IconDownloader();
iconDownloader.execute(currencyList);
}
@Override
public void onTopCurrenciesUpdated() {
}
@Override
public void onMarketCapUpdated() {
}
@Override
public void onListingUpdated() {
}
private class CurrencyLoader extends AsyncTask<Void, Void, Void>
{
@Override
protected void onPreExecute() {
super.onPreExecute();
loadingIndicatorGenerator();
}
@Override
protected Void doInBackground(Void... voids) {
coinmarketCapAPIManager.getCurrenciesFrom(listLayout.getCount(), preferenceManager.getDefaultCurrency());
return null;
}
}
private class IconDownloader extends AsyncTask<List<Currency>, Void, Void>
{
private int iconCounter;
@Override
protected Void doInBackground(List<Currency>... currencies) {
iconCounter = 0;
for(Currency currency : currencies[0])
{
String iconUrl = MoodlBox.getIconUrl(currency.getSymbol(), cryptocompareApiManager);
if(iconUrl != null)
{
MoodlBox.getBitmapFromURL(iconUrl, currency.getSymbol(), getResources(), getActivity().getBaseContext(), new MoodlboxNotifierInterface() {
@Override
public void onBitmapDownloaded(Bitmap bitmap) {
currency.setIcon(bitmap);
currency.setChartColor(getIconDominantColor(getContext(), bitmap));
countIcons(currencies[0]);
}
});
}
else
{
Drawable drawable = getDrawable(R.drawable.ic_panorama_fish_eye_24dp, getActivity().getBaseContext());
Bitmap icon = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(icon);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
icon = Bitmap.createScaledBitmap(icon, 50, 50, false);
currency.setIcon(icon);
currency.setChartColor(getIconDominantColor(getContext(), icon));
countIcons(currencies[0]);
}
}
return null;
}
private void countIcons(List<Currency> currencyList)
{
iconCounter++;
if(iconCounter == currencyList.size())
{
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if(overviewListAdapter == null)
{
overviewListAdapter = new OverviewListAdapter(Overview.this.getContext(), currencyList, getActivity());
listLayout.setAdapter(overviewListAdapter);
listLayout.setTextFilterEnabled(false);
}
else
{
overviewListAdapter.addAll(currencyList);
overviewListAdapter.notifyDataSetChanged();
}
listLayout.removeFooterView(loadingFooter);
flag_loading = false;
}
});
}
}
}
}

View File

@ -0,0 +1,784 @@
package com.herbron.moodl.Activities.HomeActivityFragments;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.graphics.Palette;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.daasuu.ei.Ease;
import com.daasuu.ei.EasingInterpolator;
import com.herbron.moodl.Activities.RecordTransactionActivity;
import com.herbron.moodl.BalanceUpdateInterface;
import com.herbron.moodl.DataNotifiers.CoinmarketcapNotifierInterface;
import com.herbron.moodl.DataNotifiers.CryptocompareNotifierInterface;
import com.herbron.moodl.CurrencyInfoUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.BalanceManager;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.CurrencyCardview;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CoinmarketCapAPIManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.BalanceSwitchManagerInterface;
import com.herbron.moodl.DataNotifiers.BalanceUpdateNotifierInterface;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static com.herbron.moodl.MoodlBox.getColor;
import static com.herbron.moodl.MoodlBox.getDrawable;
import static com.herbron.moodl.MoodlBox.getIconDominantColor;
import static com.herbron.moodl.MoodlBox.numberConformer;
import static java.lang.Math.abs;
/**
* Created by Tiji on 13/04/2018.
*/
public class Summary extends Fragment implements BalanceSwitchManagerInterface, BalanceUpdateNotifierInterface, CryptocompareNotifierInterface, CoinmarketcapNotifierInterface {
private LinearLayout currencyLayout;
private PreferencesManager preferencesManager;
private BalanceManager balanceManager;
private SwipeRefreshLayout refreshLayout;
private Dialog loadingDialog;
private String defaultCurrency;
private TextView toolbarSubtitle;
private CollapsingToolbarLayout toolbarLayout;
private Handler handler;
private Runnable updateRunnable;
private int coinCounter;
private float totalValue;
private boolean detailsChecker;
private boolean tickersChecker;
protected float totalFluctuation;
private long lastTimestamp;
private BalanceUpdateInterface balanceUpdateInterface;
private CoinmarketCapAPIManager coinmarketCapAPIManager;
private CryptocompareApiManager cryptocompareApiManager;
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View fragmentView = inflater.inflate(R.layout.homeactivity_fragment_summary, container, false);
preferencesManager = new PreferencesManager(getActivity());
balanceManager = new BalanceManager(getActivity());
coinmarketCapAPIManager = CoinmarketCapAPIManager.getInstance(getActivity());
cryptocompareApiManager = CryptocompareApiManager.getInstance(getActivity());
currencyLayout = fragmentView.findViewById(R.id.currencyListLayout);
refreshLayout = fragmentView.findViewById(R.id.swiperefreshsummary);
toolbarSubtitle = fragmentView.findViewById(R.id.toolbarSubtitle);
resetCounters();
setListener((BalanceUpdateInterface) getActivity());
defaultCurrency = preferencesManager.getDefaultCurrency();
cryptocompareApiManager.addListener(this);
coinmarketCapAPIManager.addListener(this);
handler = new Handler();
initiateUpdateRunnable();
refreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateAll(false);
}
}
);
handler.postDelayed(updateRunnable, 10000);
toolbarLayout = fragmentView.findViewById(R.id.toolbar_layout);
toolbarLayout.setForegroundGravity(Gravity.CENTER);
setupAddCurrencyButton(fragmentView);
updateAll(true);
setupDrawerButton(fragmentView);
generateSplashScreen();
return fragmentView;
}
public void setListener(BalanceUpdateInterface balanceUpdateInterface)
{
this.balanceUpdateInterface = balanceUpdateInterface;
}
private void setupDrawerButton(View view)
{
ImageButton drawerButton = view.findViewById(R.id.drawer_button);
drawerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DrawerLayout drawerLayout = getActivity().findViewById(R.id.drawer_layout);
if(drawerLayout.isDrawerOpen(GravityCompat.START))
{
drawerLayout.closeDrawers();
}
else
{
drawerLayout.openDrawer(GravityCompat.START);
}
}
});
}
private void initiateUpdateRunnable()
{
updateRunnable = new Runnable() {
@Override
public void run() {
lastTimestamp = 0;
if (refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
showErrorSnackbar();
Log.d("moodl", "Error > Refresh out of time");
}
if (loadingDialog.isShowing())
{
loadingDialog.dismiss();
showErrorSnackbar();
Log.d("moodl", "Error > Refresh out of time");
}
}
};
}
private void setupAddCurrencyButton(View fragmentView)
{
Button addCurrencyButton = fragmentView.findViewById(R.id.buttonAddTransaction);
addCurrencyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent addIntent = new Intent(getActivity(), RecordTransactionActivity.class);
startActivity(addIntent);
}
});
}
private void generateSplashScreen()
{
loadingDialog = new Dialog(getActivity(), android.R.style.Theme_Black_NoTitleBar_Fullscreen);
Random random = new Random();
LinearLayout splashLayout = (LinearLayout) LayoutInflater.from(getActivity().getBaseContext()).inflate(R.layout.splash_screen, null, true);
LinearLayout animatedLayout = splashLayout.findViewById(R.id.animatedViewsLayout);
File cacheDir = new File(getActivity().getBaseContext().getCacheDir().getAbsolutePath());
File[] cacheFiles = cacheDir.listFiles();
if(cacheFiles.length > 4)
{
for(int i = 0; i < 4; i++)
{
File cachedIcon = null;
while(cachedIcon == null || cachedIcon.isDirectory())
{
cachedIcon = cacheFiles[random.nextInt(cacheFiles.length)];
}
Bitmap icon = BitmapFactory.decodeFile(cachedIcon.getAbsolutePath());
Bitmap result = Bitmap.createBitmap(150, 150, icon.getConfig());
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(ContextCompat.getColor(getActivity().getBaseContext(), R.color.white));
Canvas canvas = new Canvas(result);
canvas.drawCircle(result.getHeight()/2, result.getWidth()/2, 75, paint);
canvas.drawBitmap(Bitmap.createScaledBitmap(icon, 100, 100, false), result.getHeight()/2 - 50, result.getWidth()/2 - 50, null);
((ImageView) animatedLayout.getChildAt(i)).setImageBitmap(result);
ObjectAnimator animator = ObjectAnimator.ofFloat(animatedLayout.getChildAt(i), "translationY", 0, -100, 0);
animator.setInterpolator(new EasingInterpolator(Ease.CIRC_IN_OUT));
animator.setStartDelay(i*200);
animator.setDuration(1500);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.start();
}
}
else
{
/*ImageView appNameImageView = splashLayout.findViewById(R.id.appNameImageView);
appNameImageView.setVisibility(View.VISIBLE);*/
animatedLayout.setVisibility(View.GONE);
}
loadingDialog.setContentView(splashLayout);
loadingDialog.show();
}
@Override
public void onResume() {
super.onResume();
displayBalance(preferencesManager.isBalanceHidden());
if(!defaultCurrency.equals(preferencesManager.getDefaultCurrency()))
{
defaultCurrency = preferencesManager.getDefaultCurrency();
updateAll(true);
}
else
{
updateAll(preferencesManager.mustUpdateSummary());
}
}
private void updateAll(boolean mustUpdate)
{
if(System.currentTimeMillis()/1000 - lastTimestamp > 60 || mustUpdate)
{
if(!refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(true);
}
lastTimestamp = System.currentTimeMillis() / 1000;
resetCounters();
DataUpdater updater = new DataUpdater();
updater.execute();
}
else
{
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
}
private void showErrorSnackbar()
{
Snackbar.make(getActivity().findViewById(R.id.content_frame), getString(R.string.error_update_data), Snackbar.LENGTH_LONG)
.setAction(getString(R.string.update), new View.OnClickListener() {
@Override
public void onClick(View view) {
updateAll(true);
}
})
.show();
}
private void resetCounters()
{
coinCounter = 0;
}
private void adaptView(float totalValue, float totalFluctuation)
{
this.totalValue = totalValue;
this.totalFluctuation = totalFluctuation;
final List<Currency> renderedCurrencies = new ArrayList<>();
if (balanceManager.getTotalBalance() != null)
{
for (int i = 0; i < balanceManager.getTotalBalance().size(); i++) {
final Currency currency = balanceManager.getTotalBalance().get(i);
if ((Math.abs(currency.getBalance() * currency.getValue()) >= preferencesManager.getMinimumAmount())) {
//currencyView.add(layoutGenerator.getInfoLayout(currency, totalValue, preferencesManager.isBalanceHidden()));
renderedCurrencies.add(currency);
}
}
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
currencyLayout.removeAllViews();
for(int i = 0; i < renderedCurrencies.size(); i++)
{
currencyLayout.addView(new CurrencyCardview(getActivity(), renderedCurrencies.get(i), getActivity(), preferencesManager.isBalanceHidden()));
}
if(loadingDialog.isShowing())
{
loadingDialog.dismiss();
}
updateTitle();
handler.removeCallbacks(updateRunnable);
}
});
}
private void countCoins(boolean isCoin, boolean isDetails, boolean isTickers)
{
if(isCoin)
{
coinCounter++;
}
if(isTickers)
{
tickersChecker = true;
}
if(isDetails)
{
detailsChecker = true;
}
if(balanceManager.getTotalBalance() != null)
{
if(balanceManager.getTotalBalance().size() == 0)
{
updateNoBalance();
}
else
{
if(coinCounter >= balanceManager.getTotalBalance().size() && detailsChecker && tickersChecker)
{
UiHeavyLoadCalculator uiHeavyLoadCalculator = new UiHeavyLoadCalculator();
uiHeavyLoadCalculator.setOnUiEndListener(new UiHeavyLoadCalculator.OnUiEndListener() {
@Override
public void onEnd(float totalValue, float totalFluctuation) {
refreshLayout.setRefreshing(false);
adaptView(totalValue, totalFluctuation);
}
});
uiHeavyLoadCalculator.execute(getActivity().getBaseContext(), balanceManager, coinmarketCapAPIManager);
}
}
}
}
private void updateNoBalance()
{
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
refreshLayout.setRefreshing(false);
currencyLayout.removeAllViews();
if(loadingDialog.isShowing())
{
loadingDialog.dismiss();
}
updateTitle();
}
});
}
private void computeTotalValue()
{
for(int i = 0; i < currencyLayout.getChildCount(); i++)
{
if(currencyLayout.getChildAt(i) instanceof CurrencyCardview)
{
((CurrencyCardview) currencyLayout.getChildAt(i)).updateOwnedValues(totalValue, preferencesManager.isBalanceHidden());
}
}
}
protected void updateTitle()
{
computeTotalValue();
float totalFluctuationPercentage = totalFluctuation / (totalValue - totalFluctuation) * 100;
if(preferencesManager.isBalanceHidden())
{
if(Double.isNaN(totalFluctuationPercentage))
{
updateHideBalanceTitle(0);
balanceUpdateInterface.onBalanceUpdated(0);
}
else
{
updateHideBalanceTitle(totalFluctuationPercentage);
balanceUpdateInterface.onBalanceUpdated(totalFluctuationPercentage);
}
}
else
{
if(Double.isNaN(totalFluctuation))
{
updateBalanceDisplayedTitle(0);
balanceUpdateInterface.onBalanceUpdated(0);
}
else
{
updateBalanceDisplayedTitle(totalFluctuationPercentage);
balanceUpdateInterface.onBalanceUpdated(totalValue);
}
}
}
public void updateBalanceDisplayedTitle(float totalFluctuationPercentage)
{
toolbarLayout.setTitle(PlaceholderUtils.getValueString(numberConformer(totalValue), getActivity()));
toolbarLayout.setCollapsedTitleTextColor(Color.WHITE);
toolbarLayout.setExpandedTitleColor(Color.WHITE);
toolbarSubtitle.setVisibility(View.VISIBLE);
if(totalFluctuation > 0)
{
toolbarSubtitle.setTextColor(getResources().getColor(R.color.increase));
}
else
{
toolbarSubtitle.setTextColor(getResources().getColor(R.color.decrease));
}
if(totalFluctuation == 0)
{
toolbarSubtitle.setText(PlaceholderUtils.getValueString(numberConformer(totalValue), getActivity()));
toolbarSubtitle.setTextColor(-1275068417);
}
else
{
toolbarSubtitle.setText(PlaceholderUtils.getValuePercentageString(numberConformer(totalFluctuation), numberConformer(totalFluctuationPercentage), getActivity()));
}
}
private void updateHideBalanceTitle(float totalFluctuationPercentage)
{
toolbarLayout.setTitle(PlaceholderUtils.getPercentageString(numberConformer(totalFluctuationPercentage), getActivity()));
toolbarSubtitle.setVisibility(View.GONE);
if(totalFluctuation > 0)
{
toolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.increase));
toolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.increase));
}
else
{
toolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.decrease));
toolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.decrease));
}
}
@Override
public void buttonCheckedChange() {
preferencesManager.switchBalanceHiddenState();
displayBalance(preferencesManager.isBalanceHidden());
}
@Override
public void onBalanceDataUpdated() {
final List<Currency> balance = balanceManager.getTotalBalance();
if(balance != null && balance.size() > 0)
{
for(int i = 0; i < balance.size(); i++)
{
balance.get(i).updatePrice(getActivity(), defaultCurrency, new CurrencyInfoUpdateNotifierInterface() {
@Override
public void onTimestampPriceUpdated(String price) {
}
@Override
public void onHistoryDataUpdated() {
}
@Override
public void onPriceUpdated(Currency currency) {
countCoins(true, false, false);
}
});
}
}
else
{
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
countCoins(false, false, false);
}
});
}
}
@Override
public void onBalanceError(String error)
{
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
generateSnackBarError(error);
}
});
}
private void generateSnackBarError(String error)
{
View view = getActivity().findViewById(R.id.content_frame);
switch (error)
{
case "com.android.volley.AuthFailureError":
preferencesManager.disableHitBTC();
Snackbar.make(view, getString(R.string.invalid_keys_hitbtc), Snackbar.LENGTH_LONG)
.show();
refreshLayout.setRefreshing(false);
updateAll(true);
break;
case "API-key format invalid.":
preferencesManager.disableBinance();
Snackbar.make(view, getString(R.string.invalid_keys_binance), Snackbar.LENGTH_LONG)
.show();
updateAll(true);
break;
case "com.android.volley.NoConnectionError: java.net.UnknownHostException: Unable to resolve host \"api.hitbtc.com\": No address associated with hostname":
Snackbar.make(view, getString(R.string.cannot_resole_host), Snackbar.LENGTH_LONG)
.show();
break;
case "com.android.volley.TimeoutError":
break;
default:
Snackbar.make(view, R.string.unexpected, Snackbar.LENGTH_LONG)
.show();
Log.d("moodl", error);
updateAll(false);
}
}
@Override
public void onDetailsUpdated() {
countCoins(false, true, false);
}
@Override
public void onExchangesUpdated() {
}
@Override
public void onCurrenciesRetrieved(List<Currency> currencyList) {
}
@Override
public void onTopCurrenciesUpdated() {
}
@Override
public void onMarketCapUpdated() {
}
@Override
public void onListingUpdated() {
countCoins(false, false, true);
}
private static class UiHeavyLoadCalculator extends AsyncTask<Object, Integer, Void>
{
private float totalValue = 0;
private float totalFluctuation = 0;
private BalanceManager balanceManager;
private CoinmarketCapAPIManager coinmarketCapAPIManager;
private OnUiEndListener onUiEndListener;
public void setOnUiEndListener(OnUiEndListener onUiEndListener)
{
this.onUiEndListener = onUiEndListener;
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
totalValue = 0;
totalFluctuation = 0;
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
}
@Override
protected Void doInBackground(Object... params)
{
if(Looper.myLooper() == null)
{
Looper.prepare();
}
Context baseContext = (Context) params[0];
balanceManager = (BalanceManager) params[1];
coinmarketCapAPIManager = (CoinmarketCapAPIManager) params[2];
balanceManager.sortCoins();
for(int i = 0; i < balanceManager.getTotalBalance().size(); i++)
{
final Currency localCurrency = balanceManager.getTotalBalance().get(i);
localCurrency.setTickerId(coinmarketCapAPIManager.getTickerIdForSymbol(localCurrency.getSymbol()));
localCurrency.setChartColor(getIconDominantColor(baseContext, localCurrency.getIcon()));
loadCurrency(localCurrency);
totalValue += localCurrency.getValue() * localCurrency.getBalance();
totalFluctuation += localCurrency.getValue() * localCurrency.getBalance() * (localCurrency.getDayFluctuationPercentage() / 100);
balanceManager.getTotalBalance().set(i, localCurrency);
}
return null;
}
private void loadCurrency(Currency currency)
{
currency.setName(balanceManager.getCurrencyName(currency.getSymbol()));
currency.setId(balanceManager.getCurrencyId(currency.getSymbol()));
}
@Override
protected void onPostExecute(Void result)
{
onUiEndListener.onEnd(totalValue, totalFluctuation);
}
public interface OnUiEndListener
{
void onEnd(float totalValue, float totalFluctuation);
}
}
private void displayBalance(boolean hideBalance)
{
updateTitle();
if(hideBalance)
{
for(int i = 0; i < currencyLayout.getChildCount(); i++)
{
currencyLayout.getChildAt(i).findViewById(R.id.currencyPortfolioDominance).setVisibility(View.VISIBLE);
currencyLayout.getChildAt(i).findViewById(R.id.percentageOwnedTextView).setVisibility(View.VISIBLE);
currencyLayout.getChildAt(i).findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.GONE);
}
}
else
{
for(int i = 0; i < currencyLayout.getChildCount(); i++)
{
currencyLayout.getChildAt(i).findViewById(R.id.currencyPortfolioDominance).setVisibility(View.INVISIBLE);
currencyLayout.getChildAt(i).findViewById(R.id.percentageOwnedTextView).setVisibility(View.GONE);
currencyLayout.getChildAt(i).findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.VISIBLE);
}
}
}
private class DataUpdater extends AsyncTask<Void, Integer, Void>
{
@Override
protected Void doInBackground(Void... params)
{
if(!coinmarketCapAPIManager.isUpToDate())
{
coinmarketCapAPIManager.updateListing();
}
else
{
countCoins(false, false, true);
}
if(!cryptocompareApiManager.isDetailsUpToDate())
{
cryptocompareApiManager.updateDetails();
}
else
{
countCoins(false, true, false);
}
balanceManager.updateTotalBalance();
return null;
}
}
}

View File

@ -0,0 +1,455 @@
package com.herbron.moodl.Activities.HomeActivityFragments;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import com.herbron.moodl.Activities.CurrencyListActivity;
import com.herbron.moodl.DataNotifiers.CoinmarketcapNotifierInterface;
import com.herbron.moodl.DataNotifiers.CryptocompareNotifierInterface;
import com.herbron.moodl.CurrencyInfoUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.CurrencyCardview;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CoinmarketCapAPIManager;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.DataManagers.WatchlistManager;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import com.herbron.moodl.R;
import com.jmedeisis.draglinearlayout.DragLinearLayout;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import static com.herbron.moodl.MoodlBox.collapseW;
import static com.herbron.moodl.MoodlBox.expandW;
import static com.herbron.moodl.MoodlBox.getIconDominantColor;
/**
* Created by Tiji on 13/04/2018.
*/
public class Watchlist extends Fragment implements CryptocompareNotifierInterface {
private WatchlistManager watchlistManager;
private View view;
private int watchlistCounter;
private CryptocompareApiManager cryptocompareApiManager;
private SwipeRefreshLayout refreshLayout;
private DragLinearLayout dragLinearLayout;
private long lastTimestamp;
private PreferencesManager preferencesManager;
private String defaultCurrency;
private CoinmarketCapAPIManager coinmarketCapAPIManager;
private boolean tickerUpdated;
private boolean detailsUpdated;
private boolean editModeEnabled;
private DatabaseManager databaseManager;
private ImageButton editButton;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.homeactivity_fragment_watchlist, container, false);
refreshLayout = view.findViewById(R.id.swiperefreshwatchlist);
dragLinearLayout = view.findViewById(R.id.linearLayoutWatchlist);
cryptocompareApiManager = CryptocompareApiManager.getInstance(getActivity().getBaseContext());
preferencesManager = new PreferencesManager(getActivity().getBaseContext());
databaseManager = new DatabaseManager(getActivity().getBaseContext());
lastTimestamp = 0;
defaultCurrency = preferencesManager.getDefaultCurrency();
coinmarketCapAPIManager = CoinmarketCapAPIManager.getInstance(getActivity());
tickerUpdated = false;
cryptocompareApiManager.addListener(this);
updateTickerList();
dragLinearLayout.setOnViewSwapListener(new DragLinearLayout.OnViewSwapListener() {
@Override
public void onSwap(View firstView, int firstPosition, View secondView, int secondPosition) {
CurrencyCardview currencyCardviewMoved = (CurrencyCardview) firstView;
CurrencyCardview currencyCardviewSwaped = (CurrencyCardview) secondView;
databaseManager.updateWatchlistPosition(currencyCardviewMoved.getCurrency().getSymbol(), secondPosition);
databaseManager.updateWatchlistPosition(currencyCardviewSwaped.getCurrency().getSymbol(), firstPosition);
}
});
editModeEnabled = false;
watchlistManager = new WatchlistManager(getActivity().getBaseContext());
updateWatchlist(true);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateWatchlist(false);
}
});
setupAddWatchlistButton();
setupDrawerButton();
setupEditButton();
return view;
}
private void updateTickerList()
{
ListingUpdater listingUpdater = new ListingUpdater();
listingUpdater.execute();
}
private class ListingUpdater extends AsyncTask<Void, Integer, Void> implements CoinmarketcapNotifierInterface {
@Override
protected Void doInBackground(Void... voids) {
coinmarketCapAPIManager.addListener(this);
if(!coinmarketCapAPIManager.isUpToDate())
{
coinmarketCapAPIManager.updateListing();
}
else
{
tickerUpdated = true;
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
checkUpdatedData();
}
});
}
return null;
}
@Override
public void onCurrenciesRetrieved(List<Currency> currencyList) {
}
@Override
public void onTopCurrenciesUpdated() {
}
@Override
public void onMarketCapUpdated() {
}
@Override
public void onListingUpdated() {
tickerUpdated = true;
checkUpdatedData();
}
}
private void disableEdition()
{
editButton.setBackground(MoodlBox.getDrawable(R.drawable.check_to_edit, getActivity().getBaseContext()));
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
AnimatedVectorDrawable animatedVectorDrawable = (AnimatedVectorDrawable) editButton.getBackground();
animatedVectorDrawable.start();
}
editModeEnabled = false;
for(int i = 0; i < dragLinearLayout.getChildCount(); i++)
{
View watchlistElement = dragLinearLayout.getChildAt(i);
if(watchlistElement instanceof CurrencyCardview)
{
watchlistElement.setClickable(true);
collapseW(watchlistElement.findViewById(R.id.deleteCardWatchlist));
collapseW(watchlistElement.findViewById(R.id.dragCardWatchlist));
}
}
}
private void enableEdition()
{
editButton.setBackground(MoodlBox.getDrawable(R.drawable.edit_to_check, getActivity().getBaseContext()));
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
AnimatedVectorDrawable animatedVectorDrawable = (AnimatedVectorDrawable) editButton.getBackground();
animatedVectorDrawable.start();
}
editModeEnabled = true;
for(int i = 0; i < dragLinearLayout.getChildCount(); i++)
{
View watchlistElement = dragLinearLayout.getChildAt(i);
if(watchlistElement instanceof CurrencyCardview)
{
watchlistElement.setClickable(false);
expandW(watchlistElement.findViewById(R.id.deleteCardWatchlist));
expandW(watchlistElement.findViewById(R.id.dragCardWatchlist));
}
}
}
private void setupEditButton()
{
editButton = view.findViewById(R.id.edit_button);
editButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(editModeEnabled)
{
disableEdition();
}
else
{
enableEdition();
}
}
});
}
private void setupAddWatchlistButton()
{
Button addWatchlistButton = view.findViewById(R.id.buttonAddWatchlist);
addWatchlistButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(editModeEnabled)
{
disableEdition();
}
Intent selectionIntent = new Intent(getActivity(), CurrencyListActivity.class);
selectionIntent.putExtra("isWatchList", true);
startActivity(selectionIntent);
}
});
}
private void setupDrawerButton()
{
ImageButton drawerButton = view.findViewById(R.id.drawer_button);
drawerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DrawerLayout drawerLayout = getActivity().findViewById(R.id.drawer_layout);
if(drawerLayout.isDrawerOpen(GravityCompat.START))
{
drawerLayout.closeDrawers();
}
else
{
drawerLayout.openDrawer(GravityCompat.START);
}
}
});
}
@Override
public void onResume()
{
super.onResume();
if(!defaultCurrency.equals(preferencesManager.getDefaultCurrency()))
{
defaultCurrency = preferencesManager.getDefaultCurrency();
updateWatchlist(true);
}
else
{
updateWatchlist(preferencesManager.mustUpdateWatchlist());
}
}
private void updateWatchlist(boolean mustUpdate)
{
if(System.currentTimeMillis()/1000 - lastTimestamp > 60 || mustUpdate)
{
if(!refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(true);
}
lastTimestamp = System.currentTimeMillis()/1000;
detailsUpdated = false;
AsyncTask<Void, Integer, Void> watchlistUpdater = new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... voids) {
watchlistManager.updateWatchlist();
if(!cryptocompareApiManager.isDetailsUpToDate())
{
cryptocompareApiManager.updateDetails();
}
else
{
detailsUpdated = true;
checkUpdatedData();
}
return null;
}
};
watchlistUpdater.execute();
}
else
{
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
}
private void checkUpdatedData()
{
if(tickerUpdated && detailsUpdated)
{
WatchlistUpdater watchlistUpdater = new WatchlistUpdater();
watchlistUpdater.execute();
if(watchlistManager.getWatchlist().size() == 0)
{
generateCards();
}
}
}
private void generateCards()
{
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
dragLinearLayout.removeAllViews();
view.findViewById(R.id.progressBarWatchlist).setVisibility(View.GONE);
view.findViewById(R.id.buttonAddWatchlist).setVisibility(View.VISIBLE);
for(Currency currency : watchlistManager.getWatchlist())
{
View addedView = new CurrencyCardview(getActivity().getBaseContext(), currency, getActivity());
dragLinearLayout.addDragView(addedView, addedView.findViewById(R.id.dragCardWatchlist));
}
}
});
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
private void countWatchlist()
{
watchlistCounter++;
if(watchlistCounter >= watchlistManager.getWatchlist().size())
{
generateCards();
}
}
public int getCurrencyId(String symbol)
{
int id = 0;
try {
JSONObject jsonObject = new JSONObject(cryptocompareApiManager.getCoinInfosHashmap().get(symbol));
id = jsonObject.getInt("Id");
} catch (JSONException e) {
e.printStackTrace();
} catch (NullPointerException e) {
Log.d("moodl", "ID not found");
e.printStackTrace();
}
return id;
}
@Override
public void onDetailsUpdated() {
detailsUpdated = true;
checkUpdatedData();
}
@Override
public void onExchangesUpdated() {
}
private class WatchlistUpdater extends AsyncTask<Void, Integer, Void>
{
@Override
protected void onPreExecute()
{
watchlistCounter = 0;
}
@Override
protected Void doInBackground(Void... voids) {
for(final Currency currency : watchlistManager.getWatchlist())
{
currency.setTickerId(coinmarketCapAPIManager.getTickerIdForSymbol(currency.getSymbol()));
currency.setId(getCurrencyId(currency.getSymbol()));
currency.updatePrice(getActivity(), preferencesManager.getDefaultCurrency(), new CurrencyInfoUpdateNotifierInterface() {
@Override
public void onTimestampPriceUpdated(String price) {
}
@Override
public void onHistoryDataUpdated() {
}
@Override
public void onPriceUpdated(Currency successCurrency) {
String iconUrl = MoodlBox.getIconUrl(currency.getSymbol(), cryptocompareApiManager);
MoodlBox.getBitmapFromURL(iconUrl, currency.getSymbol(), getResources(), getActivity().getBaseContext(), new MoodlboxNotifierInterface() {
@Override
public void onBitmapDownloaded(Bitmap bitmapIcon) {
currency.setIcon(bitmapIcon);
currency.setChartColor(getIconDominantColor(getContext(), bitmapIcon));
countWatchlist();
}
});
}
});
}
return null;
}
}
}

View File

@ -0,0 +1,737 @@
package com.herbron.moodl.Activities;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.herbron.moodl.Activities.RecordTransactionFragments.BuyFragment;
import com.herbron.moodl.Activities.RecordTransactionFragments.SellFragment;
import com.herbron.moodl.CurrencyInfoUpdateNotifierInterface;
import com.herbron.moodl.CustomAdapters.PairRecordListAdapter;
import com.herbron.moodl.CustomLayouts.CustomRecordFragment;
import com.herbron.moodl.CustomLayouts.CustomViewPager;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.Pair;
import com.herbron.moodl.DataNotifiers.CryptocompareNotifierInterface;
import com.herbron.moodl.CustomAdapters.CoinRecordListAdapter;
import com.herbron.moodl.CustomLayouts.CustomTabLayout;
import com.herbron.moodl.CustomAdapters.ExchangeRecordListAdapter;
import com.herbron.moodl.CustomAdapters.RecordTransactionPageAdapter;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.List;
public class RecordTransactionActivity extends AppCompatActivity implements CurrencyInfoUpdateNotifierInterface, CryptocompareNotifierInterface {
private Toolbar toolbar;
private ImageView currencyIconImageView;
private Currency currency;
private Exchange exchange;
private Pair pair;
private CryptocompareApiManager cryptocompareApiManager;
private AutoCompleteTextView coin_autoCompleteTextView;
private AutoCompleteTextView exchange_autoCompleteTextView;
private AutoCompleteTextView pair_autoCompleteTextView;
private CustomTabLayout tabLayout;
private CustomViewPager viewPager;
private RecordTransactionPageAdapter pageAdapter;
private Animation revealAnimation;
private Animation dismissAnimation;
private LinearLayout globalTabLayouts;
private boolean isGlobalLayoutVisible;
private Intent callingIntent;
private TextWatcher coinTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
currencyIconImageView.setImageBitmap(null);
exchange_autoCompleteTextView.setEnabled(false);
exchange_autoCompleteTextView.setText("");
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(2).setEnabled(false);
((TextView) tabLayout.getTabAt(2).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
if(isGlobalLayoutVisible && globalTabLayouts.getAnimation().hasEnded())
{
globalTabLayouts.startAnimation(dismissAnimation);
}
}
@Override
public void afterTextChanged(Editable s) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record_transaction);
toolbar = findViewById(R.id.toolbar);
currencyIconImageView = findViewById(R.id.currencyIconImageView);
cryptocompareApiManager = CryptocompareApiManager.getInstance(this);
cryptocompareApiManager.addListener(this);
cryptocompareApiManager.updateExchangeList();
coin_autoCompleteTextView = findViewById(R.id.coin_autoCompleteTextView);
exchange_autoCompleteTextView = findViewById(R.id.exchange_autoCompleteTextView);
pair_autoCompleteTextView = findViewById(R.id.pair_autoCompleteTextView);
setSupportActionBar(toolbar);
setupTabLayout();
setupCoinAutoCompleteTextView();
setupExchangeAutoCompleteTextView();
setupPairAutoCompleteTextView();
setupBackButton();
}
@Override
protected void onStop() {
super.onStop();
if(callingIntent != null)
{
callingIntent.removeExtra("transactionId");
}
}
private void checkCallingIntent()
{
callingIntent = getIntent();
int transactionId = callingIntent.getIntExtra("transactionId", -1);
if(transactionId != -1)
{
List<Exchange> exchangeList;
List<Pair> pairList;
DatabaseManager databaseManager = new DatabaseManager(getBaseContext());
Transaction transaction = databaseManager.getCurrencyTransactionById(transactionId);
List<Currency> denominationList = cryptocompareApiManager.getCurrenciesDenomination();
boolean found = false;
int index = 0;
while(index < denominationList.size() && !found)
{
if(denominationList.get(index).getSymbol().equals(transaction.getSymbol()))
{
currency = denominationList.get(index);
found = true;
currency.setListener(RecordTransactionActivity.this);
updateExchangeAdapter(currency.getSymbol());
exchange_autoCompleteTextView.setEnabled(true);
IconDownloaderTask iconDownloaderTask = new IconDownloaderTask();
iconDownloaderTask.execute();
coin_autoCompleteTextView.removeTextChangedListener(coinTextWatcher);
coin_autoCompleteTextView.setText(PlaceholderUtils.getDenomination(currency.getName(), currency.getSymbol(), getBaseContext()));
coin_autoCompleteTextView.setEnabled(false);
if(globalTabLayouts.getVisibility() == View.GONE)
{
globalTabLayouts.setVisibility(View.VISIBLE);
}
globalTabLayouts.startAnimation(revealAnimation);
isGlobalLayoutVisible = true;
updateCurrencyData();
}
index++;
}
found = false;
index = 0;
switch (transaction.getType())
{
case "b":
exchangeList = cryptocompareApiManager.getExchangeList(currency.getSymbol());
while(index < exchangeList.size() && !found)
{
if(exchangeList.get(index).getName().equals(transaction.getSource()))
{
exchange = exchangeList.get(index);
exchange_autoCompleteTextView.setText(exchange.getName());
exchange_autoCompleteTextView.setEnabled(true);
updateExchangeData();
updatePairAdapter();
found = true;
}
index++;
}
pairList = exchange.getPairsFor(currency.getSymbol());
found = false;
index = 0;
while(index < pairList.size() && !found)
{
if(pairList.get(index).contains(currency.getSymbol()) && pairList.get(index).contains(transaction.getSymPair()))
{
pair = pairList.get(index);
pair_autoCompleteTextView.setText(PlaceholderUtils.getPairString(pair.getFrom(), pair.getTo(), getBaseContext()));
pair_autoCompleteTextView.setEnabled(true);
((BuyFragment) pageAdapter.getItem(0)).updatePair(pair);
//updatePairData();
found = true;
}
index++;
}
tabLayout.getTabAt(0).select();
((TextView) tabLayout.getTabAt(0).getCustomView()).setTextColor(getResources().getColor(R.color.white));
break;
case "s":
exchangeList = cryptocompareApiManager.getExchangeList(currency.getSymbol());
while(index < exchangeList.size() && !found)
{
if(exchangeList.get(index).getName().equals(transaction.getSource()))
{
exchange = exchangeList.get(index);
exchange_autoCompleteTextView.setText(exchange.getName());
exchange_autoCompleteTextView.setEnabled(true);
updateExchangeData();
updatePairAdapter();
found = true;
}
index++;
}
pairList = exchange.getPairsFor(currency.getSymbol());
found = false;
index = 0;
while(index < pairList.size() && !found)
{
if(pairList.get(index).contains(currency.getSymbol()) && pairList.get(index).contains(transaction.getSymPair()))
{
pair = pairList.get(index);
pair_autoCompleteTextView.setText(PlaceholderUtils.getPairString(pair.getFrom(), pair.getTo(), getBaseContext()));
pair_autoCompleteTextView.setEnabled(true);
((SellFragment) pageAdapter.getItem(1)).updatePair(pair);
//updatePairData();
found = true;
}
index++;
}
tabLayout.getTabAt(1).select();
((TextView) tabLayout.getTabAt(1).getCustomView()).setTextColor(getResources().getColor(R.color.white));
break;
case "t":
tabLayout.getTabAt(2).select();
((TextView) tabLayout.getTabAt(2).getCustomView()).setTextColor(getResources().getColor(R.color.white));
break;
}
}
}
public Currency getCurrency()
{
return currency;
}
private void setupTabLayout()
{
globalTabLayouts = findViewById(R.id.globalTabLayouts);
tabLayout = findViewById(R.id.transactionsTabLayout);
tabLayout.addTab(0, getResources().getString(R.string.buyText));
tabLayout.addTab(1, getResources().getString(R.string.sellText));
tabLayout.addTab(2, getResources().getString(R.string.transferText));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager = findViewById(R.id.transactionsViewPager);
pageAdapter = new RecordTransactionPageAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(pageAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
viewPager.setPagingEnabled(false);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
LinearLayout tabLayoutChildren = (LinearLayout) tabLayout.getChildAt(0);
for(int i = 0; i < tabLayoutChildren.getChildCount(); i++)
{
tabLayoutChildren.getChildAt(i).setEnabled(false);
((TextView) tabLayout.getTabAt(i).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
}
revealAnimation = AnimationUtils.loadAnimation(this, R.anim.reveal);
dismissAnimation = AnimationUtils.loadAnimation(this, R.anim.dismiss);
dismissAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
isGlobalLayoutVisible = false;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
private void setupPairAutoCompleteTextView()
{
pair_autoCompleteTextView.setThreshold(0);
pair_autoCompleteTextView.setTextColor(getResources().getColor(R.color.white));
pair_autoCompleteTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(0).setEnabled(false);
((TextView) tabLayout.getTabAt(0).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(1).setEnabled(false);
((TextView) tabLayout.getTabAt(1).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
tabLayout.getTabAt(2).select();
}
@Override
public void afterTextChanged(Editable s) {
}
});
pair_autoCompleteTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pair_autoCompleteTextView.showDropDown();
}
});
pair_autoCompleteTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
{
pair_autoCompleteTextView.showDropDown();
}
else
{
pair_autoCompleteTextView.dismissDropDown();
}
}
});
pair_autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
pair = (Pair) pair_autoCompleteTextView.getAdapter().getItem(position);
pair_autoCompleteTextView.setText(PlaceholderUtils.getPairString(pair.getFrom(), pair.getTo(), getBaseContext()));
toolbar.requestFocus();
hideSoftKeyboard(RecordTransactionActivity.this);
updatePairData();
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(0).setEnabled(true);
((TextView) tabLayout.getTabAt(0).getCustomView()).setTextColor(getResources().getColor(R.color.white));
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(1).setEnabled(true);
((TextView) tabLayout.getTabAt(1).getCustomView()).setTextColor(getResources().getColor(R.color.white));
tabLayout.getTabAt(0).select();
}
});
}
private void setupExchangeAutoCompleteTextView()
{
exchange_autoCompleteTextView.setThreshold(0);
exchange_autoCompleteTextView.setTextColor(getResources().getColor(R.color.white));
exchange_autoCompleteTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
pair_autoCompleteTextView.setEnabled(false);
pair_autoCompleteTextView.setText("");
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(0).setEnabled(false);
((TextView) tabLayout.getTabAt(0).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(1).setEnabled(false);
((TextView) tabLayout.getTabAt(1).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
tabLayout.getTabAt(2).select();
}
@Override
public void afterTextChanged(Editable s) {
}
});
exchange_autoCompleteTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
exchange_autoCompleteTextView.showDropDown();
}
});
exchange_autoCompleteTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
{
exchange_autoCompleteTextView.showDropDown();
}
else
{
exchange_autoCompleteTextView.dismissDropDown();
}
}
});
exchange_autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
exchange = (Exchange) exchange_autoCompleteTextView.getAdapter().getItem(position);
exchange_autoCompleteTextView.setText(exchange.getName());
toolbar.requestFocus();
hideSoftKeyboard(RecordTransactionActivity.this);
updatePairAdapter();
pair_autoCompleteTextView.setEnabled(true);
updateExchangeData();
}
});
}
private void updatePairAdapter()
{
PairRecordListAdapter pairAdapter = new PairRecordListAdapter(this, android.R.layout.simple_list_item_1, new ArrayList<>(exchange.getPairsFor(currency.getSymbol())));
pair_autoCompleteTextView.setAdapter(pairAdapter);
}
private void updateExchangeAdapter(String symbol)
{
ExchangeRecordListAdapter exchangeAdapter = new ExchangeRecordListAdapter(this, android.R.layout.simple_list_item_1, new ArrayList<>(cryptocompareApiManager.getExchangeList(symbol)));
exchange_autoCompleteTextView.setAdapter(exchangeAdapter);
}
private void setupCoinAutoCompleteTextView()
{
CoinRecordListAdapter adapter = new CoinRecordListAdapter(getBaseContext(), R.layout.custom_summary_coin_row, new ArrayList<>(cryptocompareApiManager.getCurrenciesDenomination()));
coin_autoCompleteTextView.setThreshold(0);
coin_autoCompleteTextView.setAdapter(adapter);
coin_autoCompleteTextView.setTextColor(getResources().getColor(R.color.white));
coin_autoCompleteTextView.addTextChangedListener(coinTextWatcher);
coin_autoCompleteTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
coin_autoCompleteTextView.showDropDown();
}
});
coin_autoCompleteTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
{
coin_autoCompleteTextView.showDropDown();
}
else
{
coin_autoCompleteTextView.dismissDropDown();
}
}
});
coin_autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
currency = (Currency) coin_autoCompleteTextView.getAdapter().getItem(position);
coin_autoCompleteTextView.setText(PlaceholderUtils.getDenomination(currency.getName(), currency.getSymbol(), getBaseContext()));
toolbar.requestFocus();
hideSoftKeyboard(RecordTransactionActivity.this);
currency.setListener(RecordTransactionActivity.this);
updateExchangeAdapter(currency.getSymbol());
exchange_autoCompleteTextView.setEnabled(true);
IconDownloaderTask iconDownloaderTask = new IconDownloaderTask();
iconDownloaderTask.execute();
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(0).setEnabled(false);
((TextView) tabLayout.getTabAt(0).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(1).setEnabled(false);
((TextView) tabLayout.getTabAt(1).getCustomView()).setTextColor(getResources().getColor(R.color.separationColor));
((LinearLayout) tabLayout.getChildAt(0)).getChildAt(2).setEnabled(true);
((TextView) tabLayout.getTabAt(2).getCustomView()).setTextColor(getResources().getColor(R.color.white));
tabLayout.getTabAt(2).select();
updateCurrencyData();
if(globalTabLayouts.getVisibility() == View.GONE)
{
globalTabLayouts.setVisibility(View.VISIBLE);
}
globalTabLayouts.startAnimation(revealAnimation);
isGlobalLayoutVisible = true;
}
});
}
private void updateCurrencyData()
{
for(int i = 0; i < pageAdapter.getCount(); i++)
{
((CustomRecordFragment) pageAdapter.getItem(i)).setCurrency(currency);
}
}
private void updateExchangeData()
{
for(int i = 0; i < pageAdapter.getCount(); i++)
{
((CustomRecordFragment) pageAdapter.getItem(i)).setExchange(exchange);
}
}
private void updatePairData()
{
for(int i = 0; i < pageAdapter.getCount(); i++)
{
((CustomRecordFragment) pageAdapter.getItem(i)).setPair(pair);
}
}
@Override
public void onTimestampPriceUpdated(String price) {
//purchasedPriceEditText.setText(price);
}
@Override
public void onHistoryDataUpdated() {
}
@Override
public void onPriceUpdated(Currency currency) {
}
@Override
public void onDetailsUpdated() {
}
@Override
public void onExchangesUpdated() {
checkCallingIntent();
}
private class IconDownloaderTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
String iconUrl = MoodlBox.getIconUrl(currency.getSymbol(), 500, cryptocompareApiManager);
if(iconUrl != null)
{
MoodlBox.getBitmapFromURL(iconUrl, currency.getSymbol(), getResources(), getBaseContext(), new MoodlboxNotifierInterface() {
@Override
public void onBitmapDownloaded(Bitmap bitmapIcon) {
runOnUiThread(new Runnable() {
@Override
public void run() {
currencyIconImageView.setImageBitmap(bitmapIcon);
}
});
}
});
}
else
{
runOnUiThread(new Runnable() {
@Override
public void run() {
currencyIconImageView.setBackground(getResources().getDrawable(R.mipmap.ic_launcher_moodl));
}
});
}
return null;
}
}
/*if(transactionId != -1)
{
setTitle(PlaceholderUtils.getEditTransactionString(coin, getBaseContext()));
DatabaseManager databaseManager = new DatabaseManager(this);
Transaction transaction = databaseManager.getCurrencyTransactionById(transactionId);
symbolTxtView.setText(transaction.getSymbol());
amountTxtView.setText(String.valueOf(transaction.getAmount()));
purchaseDate.setText(sdf.format(transaction.getTimestamp()));
feesTxtView.setText(String.valueOf(transaction.getFees()));
}
else
{
setTitle(getString(R.string.new_transaction));
purchaseDate.setText(sdf.format(calendar.getTime()));
symbolTxtView.setText(symbol);
feesTxtView.setText(String.valueOf(0));
}
currency = new Currency(coin, symbol);
purchasedDateLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createDatePicker();
}
});
purchaseDate.setKeyListener(null);
purchaseDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createDatePicker();
}
});
//initializeButtons();
currency.getTimestampPrice(this, preferenceManager.getDefaultCurrency(), new Currency.PriceCallBack() {
@Override
public void onSuccess(String price) {
purchasedPriceEditText.setText(price);
}
}, calendar.getTimeInMillis() / 1000);*/
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
private void setupBackButton()
{
ImageButton backButton = findViewById(R.id.back_button);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}

View File

@ -0,0 +1,586 @@
package com.herbron.moodl.Activities.RecordTransactionFragments;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText;
import android.support.v7.widget.AppCompatButton;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TimePicker;
import com.herbron.moodl.Activities.HomeActivity;
import com.herbron.moodl.CustomLayouts.CustomRecordFragment;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.InfoAPIManagers.Pair;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
public class BuyFragment extends CustomRecordFragment {
private TextInputEditText amoutEditText;
private TextInputEditText buyPriceEditText;
private TextInputEditText buyDateEditText;
private TextInputEditText totalValueEditText;
private TextInputEditText fees_editText;
private TextInputEditText note_editText;
private AppCompatButton saveBuyButton;
private static Spinner feesCurrencySpinner;
private static View view;
private Switch deductHoldingsSwitch;
private ArrayAdapter<String> currencyFeeAdapter;
private SimpleDateFormat sdf;
private Calendar calendar;
private PreferencesManager preferenceManager;
private static Context context;
private static Currency fragmentCurrency;
private static Exchange fragmentExchange;
private static Pair fragmentPair;
private List<String> symbolStrings;
private int transactionId;
private static Transaction transaction;
private boolean isAmountLastUpdated;
private TextWatcher amountTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
totalValueEditText.removeTextChangedListener(totalValueTextWatcher);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(isFieldCorrectlyFilled(buyPriceEditText, false) && isFieldCorrectlyFilled(amoutEditText, false))
{
if(Double.parseDouble(amoutEditText.getText().toString()) > 0)
{
Double totalValue = Double.parseDouble(buyPriceEditText.getText().toString()) * Double.parseDouble(s.toString());
totalValueEditText.setText(String.format("%f", totalValue));
}
else
{
totalValueEditText.setText("0");
}
}
else
{
totalValueEditText.setText("");
}
}
@Override
public void afterTextChanged(Editable s) {
totalValueEditText.addTextChangedListener(totalValueTextWatcher);
isAmountLastUpdated = true;
}
};
private TextWatcher totalValueTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
amoutEditText.removeTextChangedListener(amountTextWatcher);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(isFieldCorrectlyFilled(buyPriceEditText, false) && isFieldCorrectlyFilled(totalValueEditText, false))
{
if(Double.parseDouble(totalValueEditText.getText().toString()) > 0)
{
Double amount = Double.parseDouble(s.toString()) / Double.parseDouble(buyPriceEditText.getText().toString());
amoutEditText.setText(String.format("%f", amount));
}
else
{
amoutEditText.setText("0");
}
}
else
{
amoutEditText.setText("");
}
}
@Override
public void afterTextChanged(Editable s) {
amoutEditText.addTextChangedListener(amountTextWatcher);
isAmountLastUpdated = false;
}
};
private TextWatcher feesTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
totalValueEditText.removeTextChangedListener(totalValueTextWatcher);
amoutEditText.removeTextChangedListener(amountTextWatcher);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if((isFieldCorrectlyFilled(amoutEditText, false) || isFieldCorrectlyFilled(totalValueEditText, false)) && isFieldCorrectlyFilled(buyPriceEditText, false))
{
double amount = Double.parseDouble(amoutEditText.getText().toString());
double purchasePrice = Double.parseDouble(buyPriceEditText.getText().toString());
double fees;
double totalValue = Double.parseDouble(totalValueEditText.getText().toString());
String feeCurrency;
if(isAmountLastUpdated)
{
totalValue = amount * purchasePrice;
}
else
{
amount = totalValue / purchasePrice;
}
if(fees_editText.getText().toString().equals("0") || (start == 0 && before == 1 && count == 0))
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(amount * purchasePrice));
}
else
{
amoutEditText.setText(String.valueOf(totalValue / purchasePrice));
}
}
else
{
if(feesCurrencySpinner.getSelectedItemPosition() < 2)
{
feeCurrency = fragmentPair.getFrom();
}
else
{
feeCurrency = fragmentPair.getTo();
}
fees = getFees(feeCurrency, amount, purchasePrice);
if(feesCurrencySpinner.getSelectedItemPosition() % 2 == 0)
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(totalValue + fees));
}
else
{
amoutEditText.setText(String.valueOf(amount - (fees / purchasePrice)));
}
}
else
{
if(fragmentCurrency.getSymbol().equals(feeCurrency))
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(totalValue + (fees * purchasePrice)));
}
else
{
amoutEditText.setText(String.valueOf((totalValue / purchasePrice) - fees));
}
}
else
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(totalValue + fees));
}
else
{
amoutEditText.setText(String.valueOf((totalValue - fees) / purchasePrice));
}
}
}
}
}
}
@Override
public void afterTextChanged(Editable s) {
totalValueEditText.addTextChangedListener(totalValueTextWatcher);
amoutEditText.addTextChangedListener(amountTextWatcher);
}
};
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.record_transaction_fragment_buy, container, false);
context = getActivity().getApplicationContext();
calendar = Calendar.getInstance();
sdf = new SimpleDateFormat("HH:mm dd/MM/yyyy", Locale.UK);
preferenceManager = new PreferencesManager(getContext());
initializeViewElements();
return view;
}
private void checkCallingIntent()
{
Intent intent = getActivity().getIntent();
transactionId = intent.getIntExtra("transactionId", -1);
if(transactionId != -1)
{
DatabaseManager databaseManager = new DatabaseManager(context);
transaction = databaseManager.getCurrencyTransactionById(transactionId);
if(transaction.getType() == null || transaction.getType().equals("b"))
{
fillFields();
}
}
}
private void fillFields()
{
amoutEditText.setText(String.valueOf(transaction.getAmount()));
buyPriceEditText.setText(String.valueOf(transaction.getPrice()));
calendar.setTimeInMillis(transaction.getTimestamp());
buyDateEditText.setText(sdf.format(calendar.getTime()));
totalValueEditText.setText(String.valueOf(transaction.getAmount() * transaction.getPrice()));
fees_editText.setText(String.valueOf(transaction.getFees()));
note_editText.setText(transaction.getNote());
deductHoldingsSwitch.setChecked(transaction.isDeducted());
}
private void initializeViewElements()
{
totalValueEditText = view.findViewById(R.id.totalValue_editText_buy);
amoutEditText = view.findViewById(R.id.amount_editText_buy);
buyPriceEditText = view.findViewById(R.id.buyPrice_editText);
buyDateEditText = view.findViewById(R.id.buyDate_editText);
buyDateEditText.setText(sdf.format(calendar.getTime()));
buyDateEditText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createDatePicker();
}
});
feesCurrencySpinner = view.findViewById(R.id.feesCurrency_editText_buy);
currencyFeeAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, new ArrayList<>());
currencyFeeAdapter.setDropDownViewResource(R.layout.spinner_dropdown_black);
feesCurrencySpinner.setAdapter(currencyFeeAdapter);
deductHoldingsSwitch = view.findViewById(R.id.deductHoldingsBuy);
if(fragmentPair != null)
{
updateAdapter();
}
saveBuyButton = view.findViewById(R.id.saveBuyButton);
saveBuyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isFieldCorrectlyFilled(amoutEditText, true) && isFieldCorrectlyFilled(buyPriceEditText, true) && isFieldCorrectlyFilled(totalValueEditText, true))
{
double amount = Double.parseDouble(amoutEditText.getText().toString());
double purchasePrice = Double.parseDouble(buyPriceEditText.getText().toString());
double fees;
String feeCurrency;
if(feesCurrencySpinner.getSelectedItemPosition() < 1)
{
feeCurrency = fragmentPair.getFrom();
}
else
{
feeCurrency = fragmentPair.getTo();
}
fees = getFees(feeCurrency, amount, purchasePrice);
String note = note_editText.getText().toString();
DatabaseManager databaseManager = new DatabaseManager(getContext());
preferenceManager.setMustUpdateSummary(true);
if(transactionId == -1)
{
databaseManager.addTransaction(fragmentCurrency.getSymbol()
, amount
, calendar.getTime()
, purchasePrice
, fees
, note
, fragmentPair.getFrom().equals(fragmentCurrency.getSymbol()) ? fragmentPair.getTo() : fragmentPair.getFrom()
, feeCurrency
, ""
, fragmentExchange.getName()
, "b"
, feesCurrencySpinner.getSelectedItemPosition() % 2 == 0 ? "p" : "f"
, deductHoldingsSwitch.isChecked());
Intent intent = new Intent(getActivity(), HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
else
{
databaseManager.updateTransactionWithId(transactionId
, amount
, calendar.getTime()
, purchasePrice
, fees
, note
, fragmentPair.getFrom().equals(fragmentCurrency.getSymbol()) ? fragmentPair.getTo() : fragmentPair.getFrom()
, feeCurrency
, ""
, fragmentExchange.getName()
,"b"
, feesCurrencySpinner.getSelectedItemPosition() % 2 == 0 ? "p" : "f"
, deductHoldingsSwitch.isChecked());
}
getActivity().finish();
}
}
});
fees_editText = view.findViewById(R.id.fees_editText_buy);
note_editText = view.findViewById(R.id.note_editText_buy);
checkCallingIntent();
setupTextWatchers();
}
private void setupTextWatchers()
{
totalValueEditText.addTextChangedListener(totalValueTextWatcher);
amoutEditText.addTextChangedListener(amountTextWatcher);
fees_editText.addTextChangedListener(feesTextWatcher);
}
private double getFees(String feeCurrency, double amount, double purchasedPrice)
{
double fees = 0;
if(!fees_editText.getText().toString().equals(""))
{
fees = Double.parseDouble(fees_editText.getText().toString());
if(feesCurrencySpinner.getSelectedItemPosition() % 2 == 0)
{
if(fragmentCurrency.getSymbol().equals(feeCurrency))
{
fees = (100 * amount) / (100 + fees);
}
else
{
double base = (100 * purchasedPrice * amount) / (100 + fees);
fees = purchasedPrice * amount - base;
}
}
}
return fees;
}
private boolean isFieldCorrectlyFilled(TextInputEditText editText, boolean displayError)
{
String purchasedPriceText = editText.getText().toString();
double purchasedPrice;
try {
purchasedPrice = Double.parseDouble(purchasedPriceText);
if(purchasedPrice < 0)
{
if(displayError) editText.setError(getResources().getString(R.string.field_negative));
return false;
}
} catch (NumberFormatException e) {
if(displayError) editText.setError(getResources().getString(R.string.field_nan));
return false;
}
if(purchasedPriceText.equals(""))
{
if(displayError) editText.setError(getResources().getString(R.string.field_empty));
return false;
}
return true;
}
private void updateAdapter()
{
symbolStrings = new ArrayList<>();
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(fragmentPair.getFrom(), getSecureContext()));
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(fragmentPair.getTo(), getSecureContext()));
currencyFeeAdapter.clear();
currencyFeeAdapter.addAll(symbolStrings);
currencyFeeAdapter.notifyDataSetChanged();
}
private void createDatePicker()
{
DatePickerDialog datePickerDialog = new DatePickerDialog(
getContext(),
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
buyDateEditText.setText(sdf.format(calendar.getTime()));
createTimePicker();
}
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
datePickerDialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis());
datePickerDialog.show();
}
private void createTimePicker()
{
new android.app.TimePickerDialog(
getContext(),
new android.app.TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hour, int minute) {
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
buyDateEditText.setText(sdf.format(calendar.getTime()));
if(fragmentCurrency != null)
{
fragmentCurrency.getTimestampPrice(getContext(), fragmentCurrency.getSymbol().equals(fragmentPair.getFrom()) ? fragmentPair.getTo() : fragmentPair.getFrom(),calendar.getTimeInMillis() / 1000);
}
}
},
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
true
).show();
}
private static Context getSecureContext()
{
return context;
}
@Override
public void onCurrencyUpdated() {
fragmentCurrency = currency;
}
@Override
public void onExchangeUpdated() {
fragmentExchange = exchange;
}
public void updatePair(Pair pair)
{
fragmentPair = pair;
currencyFeeAdapter = new ArrayAdapter<String>(getSecureContext(), android.R.layout.simple_spinner_item, new ArrayList<>());
currencyFeeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
feesCurrencySpinner.setAdapter(currencyFeeAdapter);
symbolStrings = new ArrayList<>();
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(pair.getFrom(), getSecureContext()));
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(pair.getTo(), getSecureContext()));
currencyFeeAdapter.addAll(symbolStrings);
currencyFeeAdapter.notifyDataSetChanged();
if(transaction != null)
{
if(transaction.getFeeCurrency().equals(fragmentPair.getFrom()))
{
if(transaction.getFeeFormat().equals("p"))
{
feesCurrencySpinner.setSelection(0);
}
else
{
feesCurrencySpinner.setSelection(1);
}
}
else
{
if(transaction.getFeeFormat().equals("p"))
{
feesCurrencySpinner.setSelection(2);
}
else
{
feesCurrencySpinner.setSelection(3);
}
}
}
}
@Override
public void onPairUpdated() {
fragmentPair = pair;
fragmentCurrency.addOnTimestampPriceUpdatedListener(new Currency.OnTimestampPriceUpdatedListener() {
@Override
public void onTimeStampPriceUpdated(String price) {
((TextInputEditText) view.findViewById(R.id.buyPrice_editText)).setText(price);
updatePair(fragmentPair);
}
});
if(calendar == null)
{
calendar = Calendar.getInstance();
}
fragmentCurrency.getTimestampPrice(getSecureContext(), fragmentCurrency.getSymbol().equals(fragmentPair.getFrom()) ? fragmentPair.getTo() : fragmentPair.getFrom(), calendar.getTimeInMillis() / 1000);
}
}

View File

@ -0,0 +1,589 @@
package com.herbron.moodl.Activities.RecordTransactionFragments;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText;
import android.support.v7.widget.AppCompatButton;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TimePicker;
import com.herbron.moodl.Activities.HomeActivity;
import com.herbron.moodl.CustomLayouts.CustomRecordFragment;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.InfoAPIManagers.Pair;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
public class SellFragment extends CustomRecordFragment {
private TextInputEditText amoutEditText;
private TextInputEditText sellPriceEditText;
private TextInputEditText sellDateEditText;
private TextInputEditText totalValueEditText;
private TextInputEditText fees_editText;
private TextInputEditText note_editText;
private AppCompatButton saveSellButton;
private static Spinner feesCurrencySpinner;
private static View view;
private Switch deductHoldingsSwitch;
private ArrayAdapter<String> currencyFeeAdapter;
private SimpleDateFormat sdf;
private Calendar calendar;
private PreferencesManager preferenceManager;
private static Context context;
private static Currency fragmentCurrency;
private static Exchange fragmentExchange;
private static Pair fragmentPair;
private List<String> symbolStrings;
private int transactionId;
private static Transaction transaction;
private boolean isAmountLastUpdated;
private TextWatcher amountTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
totalValueEditText.removeTextChangedListener(totalValueTextWatcher);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(isFieldCorrectlyFilled(sellPriceEditText, false) && isFieldCorrectlyFilled(amoutEditText, false))
{
if(Double.parseDouble(amoutEditText.getText().toString()) > 0)
{
Double totalValue = Double.parseDouble(sellPriceEditText.getText().toString()) * Double.parseDouble(s.toString());
totalValueEditText.setText(String.format("%f", totalValue));
}
else
{
totalValueEditText.setText("0");
}
}
else
{
totalValueEditText.setText("");
}
}
@Override
public void afterTextChanged(Editable s) {
totalValueEditText.addTextChangedListener(totalValueTextWatcher);
isAmountLastUpdated = true;
}
};
private TextWatcher totalValueTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
amoutEditText.removeTextChangedListener(amountTextWatcher);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(isFieldCorrectlyFilled(sellPriceEditText, false) && isFieldCorrectlyFilled(totalValueEditText, false))
{
if(Double.parseDouble(totalValueEditText.getText().toString()) > 0)
{
Double amount = Double.parseDouble(s.toString()) / Double.parseDouble(sellPriceEditText.getText().toString());
amoutEditText.setText(String.format("%f", amount));
}
else
{
amoutEditText.setText("0");
}
}
else
{
amoutEditText.setText("");
}
}
@Override
public void afterTextChanged(Editable s) {
amoutEditText.addTextChangedListener(amountTextWatcher);
isAmountLastUpdated = false;
}
};
private TextWatcher feesTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
totalValueEditText.removeTextChangedListener(totalValueTextWatcher);
amoutEditText.removeTextChangedListener(amountTextWatcher);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if((isFieldCorrectlyFilled(amoutEditText, false) || isFieldCorrectlyFilled(totalValueEditText, false)) && isFieldCorrectlyFilled(sellPriceEditText, false))
{
double amount = Double.parseDouble(amoutEditText.getText().toString());
double purchasePrice = Double.parseDouble(sellPriceEditText.getText().toString());
double fees;
double totalValue = Double.parseDouble(totalValueEditText.getText().toString());
String feeCurrency;
if(isAmountLastUpdated)
{
totalValue = amount * purchasePrice;
}
else
{
amount = totalValue / purchasePrice;
}
if(fees_editText.getText().toString().equals("0") || (start == 0 && before == 1 && count == 0))
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(amount * purchasePrice));
}
else
{
amoutEditText.setText(String.valueOf(totalValue / purchasePrice));
}
}
else
{
if(feesCurrencySpinner.getSelectedItemPosition() < 2)
{
feeCurrency = fragmentPair.getFrom();
}
else
{
feeCurrency = fragmentPair.getTo();
}
fees = getFees(feeCurrency, amount, purchasePrice);
if(feesCurrencySpinner.getSelectedItemPosition() % 2 == 0)
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(totalValue - fees));
}
else
{
amoutEditText.setText(String.valueOf(amount + (fees / purchasePrice)));
}
}
else
{
if(fragmentCurrency.getSymbol().equals(feeCurrency))
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(totalValue - (fees * purchasePrice)));
}
else
{
amoutEditText.setText(String.valueOf((totalValue / purchasePrice) + fees));
}
}
else
{
if(isAmountLastUpdated)
{
totalValueEditText.setText(String.valueOf(totalValue - fees));
}
else
{
amoutEditText.setText(String.valueOf((totalValue + fees) / purchasePrice));
}
}
}
}
}
}
@Override
public void afterTextChanged(Editable s) {
totalValueEditText.addTextChangedListener(totalValueTextWatcher);
amoutEditText.addTextChangedListener(amountTextWatcher);
}
};
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.record_transaction_fragment_sell, container, false);
context = getActivity().getApplicationContext();
calendar = Calendar.getInstance();
sdf = new SimpleDateFormat("HH:mm dd/MM/yyyy", Locale.UK);
preferenceManager = new PreferencesManager(getContext());
initializeViewElements();
return view;
}
private void initializeViewElements()
{
totalValueEditText = view.findViewById(R.id.totalValue_editText_sell);
amoutEditText = view.findViewById(R.id.amount_editText_sell);
sellPriceEditText = view.findViewById(R.id.sellPrice_editText);
sellDateEditText = view.findViewById(R.id.sellDate_editText);
sellDateEditText.setText(sdf.format(calendar.getTime()));
sellDateEditText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createDatePicker();
}
});
feesCurrencySpinner = view.findViewById(R.id.feesCurrency_editText_sell);
currencyFeeAdapter = new ArrayAdapter<String>(getSecureContext(), android.R.layout.simple_spinner_item, new ArrayList<>());
currencyFeeAdapter.setDropDownViewResource(R.layout.spinner_dropdown_black);
feesCurrencySpinner.setAdapter(currencyFeeAdapter);
if(fragmentPair != null)
{
updateAdapter();
}
deductHoldingsSwitch = view.findViewById(R.id.deductHoldingsSell);
saveSellButton = view.findViewById(R.id.saveSellButton);
saveSellButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isFieldCorrectlyFilled(amoutEditText, true) && isFieldCorrectlyFilled(sellPriceEditText, true) && isFieldCorrectlyFilled(totalValueEditText, true))
{
double amount = Double.parseDouble(amoutEditText.getText().toString());
double purchasePrice = Double.parseDouble(sellPriceEditText.getText().toString());
double fees;
String feeCurrency;
if(feesCurrencySpinner.getSelectedItemPosition() < 1)
{
feeCurrency = fragmentPair.getFrom();
}
else
{
feeCurrency = fragmentPair.getTo();
}
fees = getFees(feeCurrency, amount, purchasePrice);
String note = note_editText.getText().toString();
DatabaseManager databaseManager = new DatabaseManager(getContext());
preferenceManager.setMustUpdateSummary(true);
if(transactionId == -1)
{
databaseManager.addTransaction(fragmentCurrency.getSymbol()
, amount
, calendar.getTime()
, purchasePrice
, fees
, note
, fragmentPair.getFrom().equals(fragmentCurrency.getSymbol()) ? fragmentPair.getTo() : fragmentPair.getFrom()
, feeCurrency
, ""
, fragmentExchange.getName()
, "s"
, feesCurrencySpinner.getSelectedItemPosition() % 2 == 0 ? "p" : "f"
, deductHoldingsSwitch.isChecked());
Intent intent = new Intent(getActivity(), HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
else
{
databaseManager.updateTransactionWithId(transactionId
, amount
, calendar.getTime()
, purchasePrice
, fees
, note
, fragmentPair.getFrom().equals(fragmentCurrency.getSymbol()) ? fragmentPair.getTo() : fragmentPair.getFrom()
, feeCurrency
, ""
, fragmentExchange.getName()
,"s"
, feesCurrencySpinner.getSelectedItemPosition() % 2 == 0 ? "p" : "f"
, deductHoldingsSwitch.isChecked());
}
getActivity().finish();
}
}
});
fees_editText = view.findViewById(R.id.fees_editText_sell);
note_editText = view.findViewById(R.id.note_editText_sell);
checkCallingIntent();
setupTextWatchers();
}
private void setupTextWatchers()
{
totalValueEditText.addTextChangedListener(totalValueTextWatcher);
amoutEditText.addTextChangedListener(amountTextWatcher);
fees_editText.addTextChangedListener(feesTextWatcher);
}
private double getFees(String feeCurrency, double amount, double purchasedPrice)
{
double fees = 0;
if(!fees_editText.getText().toString().equals(""))
{
fees = Double.parseDouble(fees_editText.getText().toString());
if(feesCurrencySpinner.getSelectedItemPosition() % 2 == 0)
{
if(fragmentCurrency.getSymbol().equals(feeCurrency))
{
fees = (100 * amount) / (100 + fees);
}
else
{
double base = (100 * purchasedPrice * amount) / (100 + fees);
fees = purchasedPrice * amount - base;
}
}
}
return fees;
}
private void checkCallingIntent()
{
Intent intent = getActivity().getIntent();
transactionId = intent.getIntExtra("transactionId", -1);
if(transactionId != -1)
{
DatabaseManager databaseManager = new DatabaseManager(context);
transaction = databaseManager.getCurrencyTransactionById(transactionId);
if(transaction.getType().equals("s"))
{
fillFields();
}
}
}
private void fillFields()
{
amoutEditText.setText(String.valueOf(transaction.getAmount()));
sellPriceEditText.setText(String.valueOf(transaction.getPrice()));
calendar.setTimeInMillis(transaction.getTimestamp());
sellDateEditText.setText(sdf.format(calendar.getTime()));
totalValueEditText.setText(String.valueOf(transaction.getAmount() * transaction.getPrice()));
fees_editText.setText(String.valueOf(transaction.getFees()));
note_editText.setText(transaction.getNote());
}
private void updateAdapter()
{
symbolStrings = new ArrayList<>();
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(fragmentPair.getFrom(), getSecureContext()));
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(fragmentPair.getTo(), getSecureContext()));
currencyFeeAdapter.clear();
currencyFeeAdapter.addAll(symbolStrings);
currencyFeeAdapter.notifyDataSetChanged();
}
private static Context getSecureContext()
{
return context;
}
private void createDatePicker()
{
DatePickerDialog datePickerDialog = new DatePickerDialog(
getContext(),
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
sellDateEditText.setText(sdf.format(calendar.getTime()));
createTimePicker();
}
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
datePickerDialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis());
datePickerDialog.show();
}
private void createTimePicker()
{
new android.app.TimePickerDialog(
getContext(),
new android.app.TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hour, int minute) {
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
sellDateEditText.setText(sdf.format(calendar.getTime()));
if(fragmentCurrency != null)
{
fragmentCurrency.getTimestampPrice(getContext(), fragmentCurrency.getSymbol().equals(fragmentPair.getFrom()) ? fragmentPair.getTo() : fragmentPair.getFrom(),calendar.getTimeInMillis() / 1000);
}
}
},
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
true
).show();
}
private boolean isFieldCorrectlyFilled(TextInputEditText editText, boolean displayError)
{
String purchasedPriceText = editText.getText().toString();
double purchasedPrice;
try {
purchasedPrice = Double.parseDouble(purchasedPriceText);
if(purchasedPrice < 0)
{
if(displayError) editText.setError(getResources().getString(R.string.field_negative));
return false;
}
} catch (NumberFormatException e) {
if(displayError) editText.setError(getResources().getString(R.string.field_nan));
return false;
}
if(purchasedPriceText.equals(""))
{
if(displayError) editText.setError(getResources().getString(R.string.field_empty));
return false;
}
return true;
}
@Override
public void onCurrencyUpdated() {
fragmentCurrency = currency;
}
@Override
public void onExchangeUpdated() {
fragmentExchange = exchange;
}
public void updatePair(Pair pair)
{
fragmentPair = pair;
currencyFeeAdapter = new ArrayAdapter<String>(getSecureContext(), android.R.layout.simple_spinner_item, new ArrayList<>());
currencyFeeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
feesCurrencySpinner.setAdapter(currencyFeeAdapter);
symbolStrings = new ArrayList<>();
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(pair.getFrom(), getSecureContext()));
symbolStrings.addAll(PlaceholderUtils.getFeeOptionsForSymbol(pair.getTo(), getSecureContext()));
currencyFeeAdapter.addAll(symbolStrings);
currencyFeeAdapter.notifyDataSetChanged();
if(transaction != null)
{
if(transaction.getFeeCurrency().equals(fragmentPair.getFrom()))
{
if(transaction.getFeeFormat().equals("p"))
{
feesCurrencySpinner.setSelection(0);
}
else
{
feesCurrencySpinner.setSelection(1);
}
}
else
{
if(transaction.getFeeFormat().equals("p"))
{
feesCurrencySpinner.setSelection(2);
}
else
{
feesCurrencySpinner.setSelection(3);
}
}
}
}
@Override
public void onPairUpdated() {
fragmentPair = pair;
fragmentCurrency.addOnTimestampPriceUpdatedListener(new Currency.OnTimestampPriceUpdatedListener() {
@Override
public void onTimeStampPriceUpdated(String price) {
((TextInputEditText) view.findViewById(R.id.sellPrice_editText)).setText(price);
updatePair(fragmentPair);
}
});
if(preferenceManager == null)
{
preferenceManager = new PreferencesManager(getSecureContext());
}
if(calendar == null)
{
calendar = Calendar.getInstance();
}
fragmentCurrency.getTimestampPrice(getSecureContext(), fragmentCurrency.getSymbol().equals(fragmentPair.getFrom()) ? fragmentPair.getTo() : fragmentPair.getFrom(), calendar.getTimeInMillis() / 1000);
}
}

View File

@ -0,0 +1,471 @@
package com.herbron.moodl.Activities.RecordTransactionFragments;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TimePicker;
import com.herbron.moodl.Activities.HomeActivity;
import com.herbron.moodl.CustomLayouts.CustomRecordFragment;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.R;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
public class TransferFragment extends CustomRecordFragment {
private static Currency fragmentCurrency;
private static Exchange fragmentExchange;
private Spinner fromSpinner;
private Spinner toSpinner;
private Spinner feeSpinner;
private Switch deductHoldingsSwitch;
private Button saveButton;
private int transactionId;
private Transaction transaction;
private TextInputEditText transferDateEditText;
private TextInputEditText amountEditText;
private TextInputEditText feesEditText;
private TextInputEditText noteEditText;
private SimpleDateFormat sdf;
private Calendar calendar;
private View view;
public static final String EXCHANGE_CODE = "stra:e";
public static final String WALLET_CODE = "stra:mw";
public static final String MINING_CODE = "stra:m";
public static final String ELSE_WALLET_CODE = "stra:smew";
public static final String AIRDROP_CODE = "stra:a";
public static final String UNKNOWN_CODE = "stra:unk";
public static final String FORK_CODE = "stra:fo";
private View.OnClickListener saveButtonClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isFieldCorrectlyFilled(amountEditText, true))
{
if(isTransactionPossible())
{
PreferencesManager preferencesManager = new PreferencesManager(getContext());
DatabaseManager databaseManager = new DatabaseManager(getContext());
double amount = Double.valueOf(amountEditText.getText().toString());
double fees = getFees();
if(transactionId == -1)
{
databaseManager.addTransaction(fragmentCurrency.getSymbol()
, amount
, calendar.getTime()
, 0
, fees
, noteEditText.getText().toString()
, ""
, fragmentCurrency.getSymbol()
, getDestination()
, getSource()
, "t"
, feeSpinner.getSelectedItemPosition() == 0 ? "p" : "f"
, deductHoldingsSwitch.isChecked());
Intent intent = new Intent(getActivity(), HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
else
{
databaseManager.updateTransactionWithId(transactionId
, amount
, calendar.getTime()
, 0
, fees
, noteEditText.getText().toString()
, ""
, fragmentCurrency.getSymbol()
, getDestination()
, getSource()
,"t"
, feeSpinner.getSelectedItemPosition() == 0 ? "p" : "f"
, deductHoldingsSwitch.isChecked());
}
preferencesManager.setMustUpdateSummary(true);
getActivity().finish();
}
else
{
Drawable backgroundDrawableTo = toSpinner.getBackground();
backgroundDrawableTo.mutate();
backgroundDrawableTo.setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.error), PorterDuff.Mode.SRC_ATOP));
backgroundDrawableTo.invalidateSelf();
Drawable backgroundDrawableFrom = fromSpinner.getBackground();
backgroundDrawableFrom.mutate();
backgroundDrawableFrom.setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.error), PorterDuff.Mode.SRC_ATOP));
backgroundDrawableFrom.invalidateSelf();
view.findViewById(R.id.errorLayouts).setVisibility(View.VISIBLE);
}
}
}
};
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.record_transaction_fragment_transfer, container, false);
calendar = Calendar.getInstance();
sdf = new SimpleDateFormat("HH:mm dd/MM/yyyy", Locale.UK);
initializeViewElements();
return view;
}
private void initializeViewElements()
{
fromSpinner = view.findViewById(R.id.from_transfer_spinner);
toSpinner = view.findViewById(R.id.to_transfer_spinner);
feeSpinner = view.findViewById(R.id.feesFormat_editText_transfer);
setupSpinnesr();
feesEditText = view.findViewById(R.id.fees_editText_transfer);
noteEditText = view.findViewById(R.id.note_editText_transfer);
amountEditText = view.findViewById(R.id.amount_editText_transfer);
transferDateEditText = view.findViewById(R.id.transfertDate_editText);
transferDateEditText.setText(sdf.format(calendar.getTime()));
transferDateEditText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createDatePicker();
}
});
saveButton = view.findViewById(R.id.saveTransferButton);
saveButton.setOnClickListener(saveButtonClickListener);
deductHoldingsSwitch = view.findViewById(R.id.deductHoldingsTransfer);
checkCallingIntent();
}
private void checkCallingIntent()
{
Intent intent = getActivity().getIntent();
transactionId = intent.getIntExtra("transactionId", -1);
if(transactionId != -1)
{
DatabaseManager databaseManager = new DatabaseManager(getContext());
transaction = databaseManager.getCurrencyTransactionById(transactionId);
if(transaction.getType() != null && transaction.getType().equals("t"))
{
fillFields();
}
}
}
private void fillFields()
{
setupFromSpinner();
setupToSpinner();
amountEditText.setText(String.valueOf(transaction.getAmount()));
calendar.setTimeInMillis(transaction.getTimestamp());
transferDateEditText.setText(sdf.format(calendar.getTime()));
feesEditText.setText(String.format(Locale.UK, "%f", transaction.getFees()));
noteEditText.setText(transaction.getNote());
feeSpinner.setSelection(transaction.getFeeFormat().equals("p") ? 0 : 1);
}
private void setupFromSpinner()
{
switch (transaction.getSource())
{
case EXCHANGE_CODE:
fromSpinner.setSelection(0);
break;
case WALLET_CODE:
fromSpinner.setSelection(1);
break;
case MINING_CODE:
fromSpinner.setSelection(2);
break;
case ELSE_WALLET_CODE:
fromSpinner.setSelection(3);
break;
case AIRDROP_CODE:
fromSpinner.setSelection(4);
break;
case UNKNOWN_CODE:
fromSpinner.setSelection(5);
break;
case FORK_CODE:
fromSpinner.setSelection(6);
break;
}
}
private void setupToSpinner()
{
switch (transaction.getDestination())
{
case EXCHANGE_CODE:
toSpinner.setSelection(0);
break;
case WALLET_CODE:
toSpinner.setSelection(1);
break;
case ELSE_WALLET_CODE:
toSpinner.setSelection(2);
break;
case UNKNOWN_CODE:
toSpinner.setSelection(3);
break;
}
}
private void setupSpinnesr()
{
ArrayAdapter<String> fromAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.from_transfer_options_string_array));
fromAdapter.setDropDownViewResource(R.layout.spinner_dropdown_black);
fromSpinner.setAdapter(fromAdapter);
ArrayAdapter<String> toAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.to_transfer_options_string_array));
toAdapter.setDropDownViewResource(R.layout.spinner_dropdown_black);
toSpinner.setAdapter(toAdapter);
ArrayAdapter<String> feeAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.fees_options));
feeAdapter.setDropDownViewResource(R.layout.spinner_dropdown_black);
feeSpinner.setAdapter(feeAdapter);
fromSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
Drawable backgroundDrawableFrom = fromSpinner.getBackground();
backgroundDrawableFrom.mutate();
backgroundDrawableFrom.setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.separationColor), PorterDuff.Mode.SRC_ATOP));
backgroundDrawableFrom.invalidateSelf();
view.findViewById(R.id.errorLayouts).setVisibility(View.INVISIBLE);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
toSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
Drawable backgroundDrawableTo = toSpinner.getBackground();
backgroundDrawableTo.mutate();
backgroundDrawableTo.setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.separationColor), PorterDuff.Mode.SRC_ATOP));
backgroundDrawableTo.invalidateSelf();
view.findViewById(R.id.errorLayouts).setVisibility(View.INVISIBLE);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private double getFees()
{
double fees = 0;
if(!feesEditText.getText().toString().equals(""))
{
fees = Double.parseDouble(feesEditText.getText().toString());
}
return fees;
}
private boolean isTransactionPossible()
{
Set<Integer> conflictFrom = new HashSet<>(Arrays.asList(2, 3, 4, 5, 6));
Set<Integer> conflictTo = new HashSet<>(Arrays.asList(2, 3));
return !(conflictFrom.contains(fromSpinner.getSelectedItemPosition()) && conflictTo.contains(toSpinner.getSelectedItemPosition()));
}
private String getDestination()
{
String destination = "";
switch (toSpinner.getSelectedItemPosition())
{
case 0:
destination = EXCHANGE_CODE;
break;
case 1:
destination = WALLET_CODE;
break;
case 2:
destination = ELSE_WALLET_CODE;
break;
case 3:
destination = UNKNOWN_CODE;
break;
}
return destination;
}
private String getSource()
{
String source = "";
switch (fromSpinner.getSelectedItemPosition())
{
case 0:
source = EXCHANGE_CODE;
break;
case 1:
source = WALLET_CODE;
break;
case 2:
source = MINING_CODE;
break;
case 3:
source = ELSE_WALLET_CODE;
break;
case 4:
source = AIRDROP_CODE;
break;
case 5:
source = UNKNOWN_CODE;
break;
case 6:
source = FORK_CODE;
break;
}
return source;
}
private boolean isFieldCorrectlyFilled(TextInputEditText editText, boolean displayError)
{
String purchasedPriceText = editText.getText().toString();
double purchasedPrice;
try {
purchasedPrice = Double.parseDouble(purchasedPriceText);
if(purchasedPrice < 0)
{
if(displayError) editText.setError(getResources().getString(R.string.field_negative));
return false;
}
} catch (NumberFormatException e) {
if(displayError) editText.setError(getResources().getString(R.string.field_nan));
return false;
}
if(purchasedPriceText.equals(""))
{
if(displayError) editText.setError(getResources().getString(R.string.field_empty));
return false;
}
return true;
}
private void createDatePicker()
{
DatePickerDialog datePickerDialog = new DatePickerDialog(
getContext(),
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
transferDateEditText.setText(sdf.format(calendar.getTime()));
createTimePicker();
}
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
datePickerDialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis());
datePickerDialog.show();
}
private void createTimePicker()
{
new android.app.TimePickerDialog(
getContext(),
new android.app.TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hour, int minute) {
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
transferDateEditText.setText(sdf.format(calendar.getTime()));
}
},
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
true
).show();
}
@Override
public void onCurrencyUpdated() {
fragmentCurrency = currency;
}
@Override
public void onExchangeUpdated() {
fragmentExchange = exchange;
}
@Override
public void onPairUpdated() {
}
}

View File

@ -0,0 +1,900 @@
package com.herbron.moodl.Activities;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import com.applandeo.FilePicker;
import com.applandeo.listeners.OnSelectFileListener;
import com.herbron.moodl.BuildConfig;
import com.herbron.moodl.DataManagers.DataCrypter;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.FingerprintToolkit.FingerprintDialogFragment;
import com.herbron.moodl.FingerprintToolkit.FingerprintHandler;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
}
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
Drawable gradientDrawable = getResources().getDrawable(R.drawable.gradient_background);
actionBar.setBackgroundDrawable(gradientDrawable);
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
//loadHeadersFromResource(R.xml.pref_headers, target);
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| ExchangePreferenceFragment.class.getName().equals(fragmentName)
|| MainPreferenceFragment.class.getName().equals(fragmentName);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ExchangePreferenceFragment extends PreferenceFragment {
private static final String KEY_NAME = "NAUKEY";
private Cipher cipher;
private KeyStore keyStore;
private KeyGenerator keyGenerator;
private FingerprintManager.CryptoObject cryptoObject;
private FingerprintManager fingerprintManager;
private KeyguardManager keyguardManager;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_exchange);
setHasOptionsMenu(true);
bindPreferenceSummaryToValue(findPreference("hitbtc_publickey"));
bindPreferenceSummaryToValue(findPreference("binance_publickey"));
bindPreferenceSummaryToValue(findPreference("hitbtc_privatekey"));
bindPreferenceSummaryToValue(findPreference("binance_privatekey"));
findPreference("enable_fingerprint").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
Log.d("moodl", "> " + o + " " + preference);
return (boolean) o;
}
});
findPreference("enable_hitbtc").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
boolean isChecked = ((SwitchPreference) findPreference("enable_hitbtc")).isChecked();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("mustUpdateSummary", true);
editor.apply();
return isChecked;
}
});
findPreference("enable_binance").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
boolean isChecked = ((SwitchPreference) findPreference("enable_binance")).isChecked();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("mustUpdateSummary", true);
editor.apply();
return isChecked;
}
});
startFingerprintProtocol();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
//startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
private void startFingerprintProtocol()
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity().getBaseContext());
FingerprintDialogFragment newFragment = FingerprintDialogFragment.newInstance();
SwitchPreference touchdIdSwitch = (SwitchPreference) findPreference("enable_fingerprint");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
keyguardManager = (KeyguardManager) this.getActivity().getSystemService(KEYGUARD_SERVICE);
fingerprintManager = (FingerprintManager) this.getActivity().getSystemService(FINGERPRINT_SERVICE);
try {
if(!fingerprintManager.isHardwareDetected())
{
touchdIdSwitch.setEnabled(false);
}
if(ActivityCompat.checkSelfPermission(this.getActivity().getBaseContext(), Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED)
{
touchdIdSwitch.setEnabled(false);
}
if(!fingerprintManager.hasEnrolledFingerprints())
{
touchdIdSwitch.setEnabled(false);
}
if(!keyguardManager.isKeyguardSecure())
{
touchdIdSwitch.setEnabled(false);
}
else
{
try {
generateKey();
} catch (FingerprintException e) {
e.printStackTrace();
}
if(initCipher())
{
cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this.getActivity().getBaseContext(), newFragment);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
if(preferences.getBoolean("enable_fingerprint", false))
{
newFragment.setCancelable(false);
newFragment.show(getFragmentManager(), "dialog");
}
}
@TargetApi(23)
private void generateKey() throws FingerprintException
{
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyStore.load(null);
keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (KeyStoreException
| NoSuchAlgorithmException
| NoSuchProviderException
| InvalidAlgorithmParameterException
| CertificateException
| IOException e) {
e.printStackTrace();
throw new FingerprintException(e);
}
}
@TargetApi(23)
public boolean initCipher()
{
try {
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("Failed to get Cipher", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException
| UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
private class FingerprintException extends Exception {
public FingerprintException(Exception e)
{
super(e);
}
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class MainPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_main);
findPreference("version").setSummary(BuildConfig.VERSION_NAME);
bindPreferenceSummaryToValue(findPreference("default_currency"));
bindPreferenceSummaryToValue(findPreference("minimum_value_displayed"));
PreferenceCategory developperCategory = (PreferenceCategory) findPreference("developper_category");
if(!BuildConfig.DEBUG)
{
getPreferenceScreen().removePreference(developperCategory);
}
else
{
developperCategory.getPreference(0).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
File cacheDir = getActivity().getBaseContext().getCacheDir();
File[] cachedFiles = cacheDir.listFiles();
for(int i = 0; i < cachedFiles.length; i++)
{
if(cachedFiles[i].isFile())
{
cachedFiles[i].delete();
}
}
return false;
}
});
}
findPreference("export").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Context context = getActivity().getBaseContext();
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainPreferenceFragment.this.getActivity());
View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_export_data, null, true);
dialogBuilder.setView(dialogView);
final CheckBox backupManualEntriesCheckbox = dialogView.findViewById(R.id.checkboxBackupManualEntries);
final CheckBox backupWatchlistCheckbox = dialogView.findViewById(R.id.checkboxBackupWatchlist);
final CheckBox backupKeysCheckbox = dialogView.findViewById(R.id.checkboxBackupKeys);
final CheckBox enterPasswordCheckbox = dialogView.findViewById(R.id.checkboxEnterPassword);
final TextInputLayout textInputLayoutPassword = dialogView.findViewById(R.id.textInputLayoutPassword);
final TextView textViewFilePath = dialogView.findViewById(R.id.textViewFilePath);
File backupDirectory = new File(Environment.getExternalStorageDirectory(), getString(R.string.app_name));
createDefaultBackupDirectory(backupDirectory);
textViewFilePath.setText(backupDirectory.getAbsolutePath());
textViewFilePath.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new FilePicker.Builder(getActivity(), new OnSelectFileListener() {
@Override
public void onSelect(File file) {
textViewFilePath.setText(file.getAbsolutePath());
}
}).fileType(".moodl")
.hideFiles(true)
.directory(backupDirectory.getAbsolutePath())
.mainDirectory(Environment.getExternalStorageDirectory().getAbsolutePath())
.show();
}
});
enterPasswordCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b && textInputLayoutPassword.getVisibility() == View.GONE)
{
MoodlBox.expandH(textInputLayoutPassword);
}
if(!b && textInputLayoutPassword.getVisibility() == View.VISIBLE)
{
MoodlBox.collapseH(textInputLayoutPassword);
}
}
});
dialogBuilder.setTitle(getString(R.string.create_backup));
dialogBuilder.setPositiveButton(getString(R.string.confirm), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
checkPermissions();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault());
Date currentDate = new Date();
String fileName = "Bakup_" + formatter.format(currentDate) + ".moodl";
DatabaseManager databaseManager = new DatabaseManager(getActivity().getBaseContext());
if(enterPasswordCheckbox.isChecked())
{
if(textInputLayoutPassword.getEditText().getText().equals(""))
{
textInputLayoutPassword.setError(getString(R.string.must_be_filled));
}
else
{
DataCrypter.updateKey(textInputLayoutPassword.getEditText().getText().toString());
}
}
File backupFile = new File(textViewFilePath.getText() + "/" + fileName);
try (PrintWriter printWriter = new PrintWriter(new FileWriter(backupFile, true))) {
try {
JSONObject backupJson = new JSONObject();
initiateJsonBackup(backupJson, enterPasswordCheckbox.isChecked());
if(backupManualEntriesCheckbox.isChecked())
{
backupJson.put("transactions",
databaseManager.getDatabaseBackup(getActivity().getBaseContext(),
DatabaseManager.TABLE_MANUAL_TRANSACTIONS,
enterPasswordCheckbox.isChecked()));
}
if(backupWatchlistCheckbox.isChecked())
{
backupJson.put("watchlist",
databaseManager.getDatabaseBackup(getActivity().getBaseContext(),
DatabaseManager.TABLE_WATCHLIST,
enterPasswordCheckbox.isChecked()));
}
if(backupKeysCheckbox.isChecked())
{
backupJson.put("apiKeys",
databaseManager.getDatabaseBackup(getActivity().getBaseContext(),
DatabaseManager.TABLE_EXCHANGE_KEYS,
enterPasswordCheckbox.isChecked()));
}
printWriter.write(backupJson.toString());
} catch (JSONException e) {
Log.d("moodl", "Error while creating backup json " + e.getMessage());
}
printWriter.close();
} catch (IOException e) {
Log.d("moodl", "Error > " + e);
}
dialog.dismiss();
}
});
dialogBuilder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
return false;
}
});
findPreference("import").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Context context = getActivity().getBaseContext();
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainPreferenceFragment.this.getActivity());
View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_import_data, null, true);
dialogBuilder.setView(dialogView);
final TextView textViewFilePath = dialogView.findViewById(R.id.textViewFilePath);
final TextInputLayout textInputLayoutPassword = dialogView.findViewById(R.id.textInputLayoutPassword);
final CheckBox enterPasswordCheckbox = dialogView.findViewById(R.id.checkboxEnterPassword);
final CheckBox restoreManualEntriesCheckbox = dialogView.findViewById(R.id.checkboxRestoreEntries);
final CheckBox restoreWatchlistCheckbox = dialogView.findViewById(R.id.checkboxRestoreWatchlist);
final CheckBox restoreApiKeysCheckbox = dialogView.findViewById(R.id.checkboxRestoreKeys);
final CheckBox wipeManualEntriesCheckbox = dialogView.findViewById(R.id.checkboxWipeManualEntries);
final CheckBox wipeWatchlistCheckbox = dialogView.findViewById(R.id.checkboxWipeWatchlist);
final CheckBox wipeApiKeyxCheckbox = dialogView.findViewById(R.id.checkboxWipeAPIKeys);
restoreManualEntriesCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(restoreManualEntriesCheckbox.isChecked())
{
MoodlBox.expandH(wipeManualEntriesCheckbox);
}
else
{
MoodlBox.collapseH(wipeManualEntriesCheckbox);
}
}
});
restoreWatchlistCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(restoreWatchlistCheckbox.isChecked())
{
MoodlBox.expandH(wipeWatchlistCheckbox);
}
else
{
MoodlBox.collapseH(wipeWatchlistCheckbox);
}
}
});
restoreApiKeysCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(restoreApiKeysCheckbox.isChecked())
{
MoodlBox.expandH(wipeApiKeyxCheckbox);
}
else
{
MoodlBox.collapseH(wipeApiKeyxCheckbox);
}
}
});
enterPasswordCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b && textInputLayoutPassword.getVisibility() == View.GONE)
{
MoodlBox.expandH(textInputLayoutPassword);
}
if(!b && textInputLayoutPassword.getVisibility() == View.VISIBLE)
{
MoodlBox.collapseH(textInputLayoutPassword);
}
}
});
File backupDirectory = new File(Environment.getExternalStorageDirectory(), getString(R.string.app_name));
createDefaultBackupDirectory(backupDirectory);
textViewFilePath.setText(backupDirectory.getAbsolutePath());
textViewFilePath.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new FilePicker.Builder(getActivity(), new OnSelectFileListener() {
@Override
public void onSelect(File file) {
textViewFilePath.setText(file.getAbsolutePath());
}
}).hideFiles(false)
.directory(backupDirectory.getAbsolutePath())
.mainDirectory(Environment.getExternalStorageDirectory().getAbsolutePath())
.show();
}
});
dialogBuilder.setTitle(getString(R.string.restoreBackup));
dialogBuilder.setPositiveButton(getString(R.string.confirm), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int whichButton) {
checkPermissions();
DatabaseManager databaseManager = new DatabaseManager(context);
if(enterPasswordCheckbox.isChecked())
{
DataCrypter.updateKey(textInputLayoutPassword.getEditText().getText().toString());
}
File backupFile = new File(textViewFilePath.getText().toString());
try {
FileReader fileReader = new FileReader(backupFile);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String str;
String completeFile = "";
while ((str = bufferedReader.readLine()) != null) {
completeFile += str;
}
try {
JSONObject backupJson = new JSONObject(completeFile);
String checker;
if(enterPasswordCheckbox.isChecked())
{
checker = DataCrypter.decrypt(getActivity().getBaseContext(), backupJson.getString("encodeChecker"));
}
else
{
checker = backupJson.getString("encodeChecker");
}
if(checker.equals("NaukVerification"))
{
if(restoreManualEntriesCheckbox.isChecked())
{
if(wipeManualEntriesCheckbox.isChecked())
{
databaseManager.wipeData(DatabaseManager.TABLE_MANUAL_TRANSACTIONS);
}
if(backupJson.has("transactions"))
{
JSONArray transactionsArray = backupJson.getJSONArray("transactions");
for(int i = 0; i < transactionsArray.length(); i++)
{
JSONObject transactionObject = transactionsArray.getJSONObject(i);
databaseManager.addRowTransaction(transactionObject, getActivity().getBaseContext(), enterPasswordCheckbox.isChecked());
}
}
}
if(restoreWatchlistCheckbox.isChecked())
{
if(wipeWatchlistCheckbox.isChecked())
{
databaseManager.wipeData(DatabaseManager.TABLE_WATCHLIST);
}
if(backupJson.has("watchlist"))
{
JSONArray watchlistArray = backupJson.getJSONArray("watchlist");
for(int i = 0; i < watchlistArray.length(); i++)
{
JSONObject watchlistObject = watchlistArray.getJSONObject(i);
databaseManager.addRowWatchlist(watchlistObject, getActivity().getBaseContext(), enterPasswordCheckbox.isChecked());
}
}
}
if(restoreApiKeysCheckbox.isChecked())
{
if(wipeApiKeyxCheckbox.isChecked())
{
databaseManager.wipeData(DatabaseManager.TABLE_EXCHANGE_KEYS);
}
if(backupJson.has("apiKeys"))
{
JSONArray apiArray = backupJson.getJSONArray("apiKeys");
for(int i = 0; i < apiArray.length(); i++)
{
JSONObject apiKeysObject = apiArray.getJSONObject(i);
databaseManager.addRowApiKeys(apiKeysObject, getActivity().getBaseContext(), enterPasswordCheckbox.isChecked());
}
}
}
PreferencesManager preferencesManager = new PreferencesManager(getContext());
preferencesManager.setMustUpdateSummary(true);
}
else
{
textInputLayoutPassword.setError(getString(R.string.wrong_password));
}
} catch (JSONException e) {
Log.d("moodl", "Error while creating backup json " + e);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
dialogBuilder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
return false;
}
});
DatabaseManager databaseManager = new DatabaseManager(getActivity().getBaseContext());
int disabledAcount = databaseManager.getDisabledExchangeAccountsNumber();
PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference("exchange");
if(disabledAcount > 0)
{
preferenceScreen.setWidgetLayoutResource(R.layout.alert_layout);
}
preferenceScreen.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent exchangeListIntent = new Intent(getActivity().getBaseContext(), ExchangeListActivity.class);
startActivity(exchangeListIntent);
return false;
}
});
EditTextPreference editTextPreference = (EditTextPreference) findPreference("minimum_value_displayed");
editTextPreference.setPositiveButtonText(getString(R.string.save));
editTextPreference.setNegativeButtonText(getString(R.string.cancel));
}
private void initiateJsonBackup(JSONObject backupJson, boolean mustEncrypt) throws JSONException
{
if(mustEncrypt)
{
backupJson.put("encodeChecker", DataCrypter.encrypt(getActivity().getBaseContext(), "NaukVerification"));
}
else
{
backupJson.put("encodeChecker", "NaukVerification");
}
}
private void createDefaultBackupDirectory(File backupDirectory)
{
if (!backupDirectory.exists()) {
if (!backupDirectory.mkdirs()) {
Log.d("moodl", "Error while creating directory");
}
}
}
private boolean checkPermissions() {
String[] permissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(getActivity().getBaseContext(), p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(getActivity(), listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), 100);
return false;
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
//startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -0,0 +1,7 @@
package com.herbron.moodl;
public interface BalanceSwitchManagerInterface {
void buttonCheckedChange();
}

View File

@ -0,0 +1,10 @@
package com.herbron.moodl;
/**
* Created by Administrator on 04/06/2018.
*/
public interface BalanceUpdateInterface {
void onBalanceUpdated(float value);
}

View File

@ -0,0 +1,13 @@
package com.herbron.moodl;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
public interface CurrencyInfoUpdateNotifierInterface {
void onTimestampPriceUpdated(String price);
void onHistoryDataUpdated();
void onPriceUpdated(Currency currency);
}

View File

@ -0,0 +1,120 @@
package com.herbron.moodl.CustomAdapters;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.R;
import java.util.ArrayList;
public class CoinRecordListAdapter extends ArrayAdapter<Currency> {
private CustomFilter filter;
private ArrayList<Currency> currencies, suggestions;
public CoinRecordListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Currency> currencies) {
super(context, resource, currencies);
this.currencies = currencies;
this.suggestions = currencies;
}
@Override
public int getCount() {
return currencies.size();
}
@Override
public Currency getItem(int position) {
return currencies.get(position);
}
@Override
public long getItemId(int position) {
return currencies.indexOf(getItem(position));
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Currency currency = getItem(position);
if(convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_summary_coin_row, parent, false);
}
TextView nameTxtview = convertView.findViewById(R.id.currencyName);
TextView symbolTxtView = convertView.findViewById(R.id.currencySymbol);
nameTxtview.setText(currency.getName());
symbolTxtView.setText(currency.getSymbol());
return convertView;
}
@NonNull
@Override
public Filter getFilter() {
if(filter == null)
{
filter = new CustomFilter();
}
return filter;
}
private class CustomFilter extends Filter
{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint != null && constraint.length() > 0)
{
constraint = constraint.toString().toLowerCase();
ArrayList<Currency> filters = new ArrayList<>();
for(int i = 0; i < suggestions.size(); i++)
{
if(suggestions.get(i).getName().toLowerCase().contains(constraint) || suggestions.get(i).getSymbol().toLowerCase().contains(constraint))
{
Currency currency = new Currency(suggestions.get(i).getName(), suggestions.get(i).getSymbol());
filters.add(currency);
}
}
results.count = filters.size();
results.values = filters;
}
else
{
results.count = suggestions.size();
results.values = suggestions;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results != null)
{
currencies = (ArrayList<Currency>) results.values;
}
notifyDataSetChanged();
}
}
}

View File

@ -0,0 +1,134 @@
package com.herbron.moodl.CustomAdapters;
import android.content.Context;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.R;
import java.util.ArrayList;
/**
* Created by Guitoune on 17/01/2018.
*/
public class CoinWatchlistAdapter extends BaseAdapter implements Filterable {
private ArrayList<Currency> currencies, suggestions;
private Context context;
private CustomFilter filter;
public CoinWatchlistAdapter(Context context, ArrayList<Currency> currencies) {
this.context = context;
this.currencies = currencies;
this.suggestions = currencies;
}
@Override
public int getCount() {
return currencies.size();
}
@Override
public Object getItem(int position) {
return currencies.get(position);
}
@Override
public long getItemId(int position) {
return currencies.indexOf(getItem(position));
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.custom_watchlist_coin_row, parent, false);
}
TextView currencyName = convertView.findViewById(R.id.currencyName);
TextView currencySymbol = convertView.findViewById(R.id.currencySymbol);
if (currencyName != null)
currencyName.setText(currencies.get(position).getName());
if(currencySymbol != null)
{
currencySymbol.setText(currencies.get(position).getSymbol());
}
if (position % 2 == 0)
convertView.setBackgroundColor(context.getResources().getColor(R.color.white));
else
convertView.setBackgroundColor(context.getResources().getColor(R.color.listBackground));
return convertView;
}
@NonNull
@Override
public Filter getFilter() {
if(filter == null)
{
filter = new CustomFilter();
}
return filter;
}
class CustomFilter extends Filter
{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint != null && constraint.length() > 0)
{
constraint = constraint.toString().toLowerCase();
ArrayList<Currency> filters = new ArrayList<Currency>();
for(int i = 0; i < suggestions.size(); i++)
{
if(suggestions.get(i).getName().toLowerCase().contains(constraint) || suggestions.get(i).getSymbol().toLowerCase().contains(constraint))
{
Currency currency = new Currency(suggestions.get(i).getName(), suggestions.get(i).getSymbol());
filters.add(currency);
}
}
results.count = filters.size();
results.values = filters;
}
else
{
results.count = suggestions.size();
results.values = suggestions;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results != null)
{
currencies = (ArrayList<Currency>) results.values;
}
notifyDataSetChanged();
}
}
}

View File

@ -0,0 +1,92 @@
package com.herbron.moodl.CustomAdapters;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.herbron.moodl.Activities.AddExchangeActivity;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.R;
import java.util.ArrayList;
import static com.herbron.moodl.DataManagers.DatabaseManager.BINANCE_TYPE;
import static com.herbron.moodl.DataManagers.DatabaseManager.HITBTC_TYPE;
public class ExchangeDescriptionListAdapter extends ArrayAdapter<Exchange> {
private Context context;
public ExchangeDescriptionListAdapter(Context context, ArrayList<Exchange> exchanges)
{
super(context, android.R.layout.simple_list_item_1, exchanges);
this.context = context;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Exchange exchange = getItem(position);
if(convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.exchange_cell, parent, false);
}
TextView exchangeNameTextView = convertView.findViewById(R.id.exchange_name);
TextView exchangeDescriptionTextView = convertView.findViewById(R.id.exchange_description);
ImageView accountOffImageView = convertView.findViewById(R.id.exchange_account_off_imageView);
ImageView exchangeImageView = convertView.findViewById(R.id.exchange_icon_imageView);
exchangeNameTextView.setText(exchange.getName());
exchangeDescriptionTextView.setText(exchange.getDescription());
switch (exchange.getType())
{
case BINANCE_TYPE:
exchangeImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.exchange_logo_binance));
break;
case HITBTC_TYPE:
exchangeImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.exchange_logo_hitbtc));
break;
}
if(!exchange.isEnabled())
{
accountOffImageView.setVisibility(View.VISIBLE);
}
convertView.findViewById(R.id.editExchangeInfosLayout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent editExchangeAccountIntent = new Intent(context, AddExchangeActivity.class);
editExchangeAccountIntent.putExtra("isEdit", true);
editExchangeAccountIntent.putExtra("exchangeId", exchange.getId());
editExchangeAccountIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(editExchangeAccountIntent);
}
});
convertView.findViewById(R.id.deleteExchangeInfosLayout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DatabaseManager databaseManager = new DatabaseManager(getContext());
databaseManager.deleteExchangeAccountFromId(exchange.getId());
remove(exchange);
notifyDataSetChanged();
}
});
return convertView;
}
}

View File

@ -0,0 +1,120 @@
package com.herbron.moodl.CustomAdapters;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.R;
import java.util.ArrayList;
public class ExchangeRecordListAdapter extends ArrayAdapter<Exchange> {
private CustomFilter filter;
private ArrayList<Exchange> exchanges, suggestions;
public ExchangeRecordListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Exchange> exchanges) {
super(context, resource, exchanges);
this.exchanges = exchanges;
this.suggestions = exchanges;
}
@NonNull
@Override
public Filter getFilter() {
if(filter == null)
{
filter = new CustomFilter();
}
return filter;
}
@Override
public int getCount() {
return exchanges.size();
}
@Nullable
@Override
public Exchange getItem(int position) {
return exchanges.get(position);
}
@Override
public long getItemId(int position) {
return exchanges.indexOf(getItem(position));
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Exchange exchange = getItem(position);
if(convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.simple_spinner_item, parent, false);
}
TextView nameTxtview = convertView.findViewById(R.id.textView);
nameTxtview.setTextColor(getContext().getResources().getColor(android.R.color.tab_indicator_text));
nameTxtview.setText(exchange.getName());
return convertView;
}
private class CustomFilter extends Filter
{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint != null && constraint.length() > 0)
{
constraint = constraint.toString().toLowerCase();
ArrayList<Exchange> filters = new ArrayList<>();
for(int i = 0; i < suggestions.size(); i++)
{
if(suggestions.get(i).getName().toLowerCase().contains(constraint))
{
Exchange exchange = new Exchange(suggestions.get(i));
filters.add(exchange);
}
}
results.count = filters.size();
results.values = filters;
}
else
{
results.count = suggestions.size();
results.values = suggestions;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results != null)
{
exchanges = (ArrayList<Exchange>) results.values;
}
notifyDataSetChanged();
}
}
}

View File

@ -0,0 +1,50 @@
package com.herbron.moodl.CustomAdapters;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.CurrencyCardview;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import java.util.List;
/**
* Created by Administrator on 28/05/2018.
*/
public class OverviewListAdapter extends ArrayAdapter<Currency> {
private Activity activity;
private CryptocompareApiManager cryptocompareApiManager;
public OverviewListAdapter(Context context, List<Currency> currencies, Activity activity)
{
super(context, android.R.layout.simple_expandable_list_item_1, currencies);
this.activity = activity;
cryptocompareApiManager = CryptocompareApiManager.getInstance(getContext());
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
{
Currency currency = getItem(position);
cryptocompareApiManager.getCurrencyDetailsFromSymbol(currency.getSymbol());
CurrencyCardview currencyCardview = new CurrencyCardview(getContext(), currency, activity);
LinearLayout linearLayout = new LinearLayout(getContext());
linearLayout.addView(currencyCardview);
convertView = linearLayout;
return convertView;
}
}

View File

@ -0,0 +1,121 @@
package com.herbron.moodl.CustomAdapters;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import com.herbron.moodl.DataManagers.InfoAPIManagers.Pair;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.util.ArrayList;
public class PairRecordListAdapter extends ArrayAdapter<Pair> {
private CustomFilter filter;
private ArrayList<Pair> pairs, suggestions;
public PairRecordListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Pair> pairs) {
super(context, resource, pairs);
this.pairs = pairs;
this.suggestions = pairs;
}
@NonNull
@Override
public Filter getFilter() {
if(filter == null)
{
filter = new CustomFilter();
}
return filter;
}
@Override
public int getCount() {
return pairs.size();
}
@Nullable
@Override
public Pair getItem(int position) {
return pairs.get(position);
}
@Override
public long getItemId(int position) {
return pairs.indexOf(getItem(position));
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Pair pair = getItem(position);
if(convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.simple_spinner_item, parent, false);
}
TextView pairTxtView = convertView.findViewById(R.id.textView);
pairTxtView.setTextColor(getContext().getResources().getColor(android.R.color.tab_indicator_text));
pairTxtView.setText(PlaceholderUtils.getPairString(pair.getFrom(), pair.getTo(), getContext()));
return convertView;
}
private class CustomFilter extends Filter
{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint != null && constraint.length() > 0)
{
constraint = constraint.toString().toUpperCase();
ArrayList<Pair> filters = new ArrayList<>();
for(int i = 0; i < suggestions.size(); i++)
{
if(suggestions.get(i).getFrom().contains(constraint) || suggestions.get(i).getTo().contains(constraint))
{
Pair pair = new Pair(suggestions.get(i));
filters.add(pair);
}
}
results.count = filters.size();
results.values = filters;
}
else
{
results.count = suggestions.size();
results.values = suggestions;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results != null)
{
pairs = (ArrayList<Pair>) results.values;
}
notifyDataSetChanged();
}
}
}

View File

@ -0,0 +1,44 @@
package com.herbron.moodl.CustomAdapters;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import com.herbron.moodl.Activities.RecordTransactionFragments.BuyFragment;
import com.herbron.moodl.Activities.RecordTransactionFragments.SellFragment;
import com.herbron.moodl.Activities.RecordTransactionFragments.TransferFragment;
public class RecordTransactionPageAdapter extends FragmentStatePagerAdapter {
private int tabsNumber;
public RecordTransactionPageAdapter(FragmentManager fm, int tabsNumber) {
super(fm);
this.tabsNumber = tabsNumber;
}
@Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
BuyFragment buyFragment = new BuyFragment();
return buyFragment;
case 1:
SellFragment sellFragment = new SellFragment();
return sellFragment;
case 2:
TransferFragment transferFragment = new TransferFragment();
return transferFragment;
default:
return null;
}
}
@Override
public int getCount() {
return tabsNumber;
}
}

View File

@ -0,0 +1,228 @@
package com.herbron.moodl.CustomAdapters;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.daimajia.swipe.SwipeLayout;
import com.herbron.moodl.Activities.RecordTransactionActivity;
import com.herbron.moodl.DataManagers.CurrencyData.Trade;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.R;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.Utils.TransferUtils;
import java.util.ArrayList;
import static com.herbron.moodl.MoodlBox.collapseH;
import static com.herbron.moodl.MoodlBox.getDateFromTimestamp;
import static com.herbron.moodl.MoodlBox.numberConformer;
import static java.lang.Math.abs;
import static com.herbron.moodl.Utils.TransferUtils.isBalanceRelated;
/**
* Created by Guitoune on 24/04/2018.
*/
public class TransactionListAdapter extends ArrayAdapter<Object> {
private Context context;
public TransactionListAdapter(Context context, ArrayList<Object> transactions)
{
super(context, android.R.layout.simple_list_item_1, transactions);
this.context = context;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
if(getItem(position) instanceof Transaction)
{
return generateTransactionLayout(position, parent);
}
else
{
return generateTradeLayout(position, parent);
}
}
private View generateTradeLayout(int position, ViewGroup parent)
{
Trade trade = (Trade) getItem(position);
View convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_trade_row, parent, false);
TextView amountTxtView = convertView.findViewById(R.id.amountPurchased);
TextView purchasedPrice = convertView.findViewById(R.id.purchasePrice);
TextView tradePair = convertView.findViewById(R.id.pair);
TextView dateTxtView = convertView.findViewById(R.id.tradeDate);
View tradeIndicator = convertView.findViewById(R.id.tradeIndicator);
amountTxtView.setText(String.valueOf(trade.getQty()));
purchasedPrice.setText(trade.getPrice());
dateTxtView.setText(getDateFromTimestamp(trade.getTime()));
tradePair.setText(trade.getSymbol() + "/" + trade.getPairSymbol());
if(trade.isBuyer())
{
tradeIndicator.setBackgroundColor(context.getResources().getColor(R.color.green));
}
else
{
tradeIndicator.setBackgroundColor(context.getResources().getColor(R.color.red));
}
return convertView;
}
private View generateTransactionLayout(int position, ViewGroup parent)
{
final Transaction transaction = (Transaction) getItem(position);
View convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_transaction_row, parent, false);
TextView topLeftTextView = convertView.findViewById(R.id.transactionTLTV);
TextView bottomLeftTextView = convertView.findViewById(R.id.transactionBLTV);
TextView dateTxtView = convertView.findViewById(R.id.transactionDateTextView);
TextView amountTxtView = convertView.findViewById(R.id.transactionAmountTextView);
amountTxtView.setText(String.valueOf(transaction.getAmount()));
dateTxtView.setText(getDateFromTimestamp(transaction.getTimestamp()));
LinearLayout deleteLayout = convertView.findViewById(R.id.deleteTransactionLayout);
deleteLayout.setTag(transaction.getTransactionId());
deleteLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PreferencesManager preferencesManager = new PreferencesManager(context);
DatabaseManager databaseManager = new DatabaseManager(context);
preferencesManager.setMustUpdateSummary(true);
databaseManager.deleteTransactionFromId(Integer.parseInt(view.getTag().toString()));
collapseH((View) view.getParent().getParent().getParent());
}
});
LinearLayout editLayout = convertView.findViewById(R.id.editTransactionLayout);
editLayout.setTag(transaction.getTransactionId());
editLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = ((Activity) context).getTitle().toString();
name = name.substring(1, name.indexOf("|") - 1);
Intent intent = new Intent(context, RecordTransactionActivity.class);
intent.putExtra("coin", name);
intent.putExtra("symbol", transaction.getSymbol());
intent.putExtra("transactionId", transaction.getTransactionId());
context.startActivity(intent);
}
});
View transactionIndicator = convertView.findViewById(R.id.transactionIndicator);
switch (transaction.getType())
{
case "b":
transactionIndicator.setBackgroundColor(context.getResources().getColor(R.color.increaseCandle));
topLeftTextView.setText(transaction.getSource());
bottomLeftTextView.setText(PlaceholderUtils.getToPairString(transaction.getSymPair(), transaction.getSymbol(), context));
break;
case "s":
transactionIndicator.setBackgroundColor(context.getResources().getColor(R.color.decreaseCandle));
topLeftTextView.setText(transaction.getSource());
bottomLeftTextView.setText(PlaceholderUtils.getToPairString(transaction.getSymbol(), transaction.getSymPair(), context));
break;
case "t":
transactionIndicator.setBackgroundColor(context.getResources().getColor(R.color.blue));
if(isBalanceRelated(transaction.getDestination()) && isBalanceRelated(transaction.getSource()))
{
topLeftTextView.setText(context.getString(R.string.transferText));
bottomLeftTextView.setText(PlaceholderUtils.getFromToString(TransferUtils.getLabelFor(context, transaction.getSource()), TransferUtils.getLabelFor(context, transaction.getDestination()), context));
}
else
{
if(isBalanceRelated(transaction.getDestination()))
{
topLeftTextView.setText(context.getString(R.string.depositText));
bottomLeftTextView.setText(PlaceholderUtils.getFromString(TransferUtils.getLabelFor(context, transaction.getSource()), context));
}
else
{
if(isBalanceRelated(transaction.getSource()))
{
topLeftTextView.setText(context.getString(R.string.withdrawText));
bottomLeftTextView.setText(PlaceholderUtils.getToString(TransferUtils.getLabelFor(context, transaction.getDestination()), context));
}
}
}
break;
}
setupSwipeView(convertView);
return convertView;
}
private void setupSwipeView(View view)
{
SwipeLayout swipeLayout = view.findViewById(R.id.swipeLayout);
//set show mode.
swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
//add drag edge.(If the BottomView has 'layout_gravity' attribute, this line is unnecessary)
swipeLayout.addDrag(SwipeLayout.DragEdge.Left, view.findViewById(R.id.bottom_wrapper));
swipeLayout.addSwipeListener(new SwipeLayout.SwipeListener() {
@Override
public void onClose(SwipeLayout layout) {
//when the SurfaceView totally cover the BottomView.
}
@Override
public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset) {
//you are swiping.
}
@Override
public void onStartOpen(SwipeLayout layout) {
}
@Override
public void onOpen(SwipeLayout layout) {
//when the BottomView totally show.
}
@Override
public void onStartClose(SwipeLayout layout) {
}
@Override
public void onHandRelease(SwipeLayout layout, float xvel, float yvel) {
//when user's hand released.
}
});
}
}

View File

@ -0,0 +1,28 @@
package com.herbron.moodl.CustomLayouts;
import android.content.Context;
import android.util.AttributeSet;
import com.github.mikephil.charting.charts.PieChart;
public class CustomPieChart extends PieChart {
public CustomPieChart(Context context) {
super(context);
}
public CustomPieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomPieChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean performClick() {
super.performClick();
return true;
}
}

View File

@ -0,0 +1,41 @@
package com.herbron.moodl.CustomLayouts;
import android.support.v4.app.Fragment;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.InfoAPIManagers.Pair;
public abstract class CustomRecordFragment extends Fragment {
protected Currency currency;
protected Exchange exchange;
protected Pair pair;
public void setCurrency(Currency currency)
{
this.currency = currency;
onCurrencyUpdated();
}
public void setExchange(Exchange exchange)
{
this.exchange = exchange;
onExchangeUpdated();
}
public void setPair(Pair pair)
{
this.pair = pair;
onPairUpdated();
}
public abstract void onCurrencyUpdated();
public abstract void onExchangeUpdated();
public abstract void onPairUpdated();
}

View File

@ -0,0 +1,92 @@
package com.herbron.moodl.CustomLayouts;
import android.content.Context;
import android.graphics.drawable.StateListDrawable;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.herbron.moodl.R;
public class CustomTabLayout extends TabLayout {
private LinearLayout linearLayout;
private Context context;
public CustomTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
linearLayout = (LinearLayout) getChildAt(0);
this.context = context;
}
private StateListDrawable getSellStateListDrawable() {
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {android.R.attr.state_pressed},
ContextCompat.getDrawable(context, R.drawable.unselected_tab_background));
sld.addState(new int[] {android.R.attr.state_selected},
ContextCompat.getDrawable(context, R.drawable.record_transaction_tab_background_sell));
sld.addState(new int[] {android.R.attr.state_enabled },
ContextCompat.getDrawable(context, R.drawable.unselected_tab_background));
sld.addState(new int[] { },
ContextCompat.getDrawable(context, R.drawable.disabled_tab_background));
return sld;
}
private StateListDrawable getBuyStateListDrawable() {
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {android.R.attr.state_pressed},
ContextCompat.getDrawable(context, R.drawable.unselected_tab_background));
sld.addState(new int[] {android.R.attr.state_selected},
ContextCompat.getDrawable(context, R.drawable.record_transaction_tab_background_buy));
sld.addState(new int[] {android.R.attr.state_enabled },
ContextCompat.getDrawable(context, R.drawable.unselected_tab_background));
sld.addState(new int[] { },
ContextCompat.getDrawable(context, R.drawable.disabled_tab_background));
return sld;
}
private StateListDrawable getTransferStateListDrawable() {
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {android.R.attr.state_pressed},
ContextCompat.getDrawable(context, R.drawable.unselected_tab_background));
sld.addState(new int[] {android.R.attr.state_selected},
ContextCompat.getDrawable(context, R.drawable.record_transaction_tab_background_transfer));
sld.addState(new int[] {android.R.attr.state_enabled },
ContextCompat.getDrawable(context, R.drawable.unselected_tab_background));
sld.addState(new int[] { },
ContextCompat.getDrawable(context, R.drawable.disabled_tab_background));
return sld;
}
public void addTab(int index, String label) {
TextView textView = new TextView(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setText(label);
textView.setGravity(GRAVITY_CENTER);
textView.setTextColor(getResources().getColor(R.color.separationColor));
addTab(newTab().setCustomView(textView));
View tabView = linearLayout.getChildAt(linearLayout.getChildCount() - 1);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams();
params.setMargins(2, 0, 2, 0);
tabView.setLayoutParams(params);
switch (index)
{
case 0:
tabView.setBackground(getBuyStateListDrawable());
break;
case 1:
tabView.setBackground(getSellStateListDrawable());
break;
case 2:
tabView.setBackground(getTransferStateListDrawable());
break;
}
}
}

View File

@ -0,0 +1,42 @@
package com.herbron.moodl.CustomLayouts;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Created by Administrator on 14/05/2018.
*/
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -0,0 +1,51 @@
package com.herbron.moodl.CustomLayouts;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.design.widget.TextInputEditText;
import android.text.TextPaint;
import android.util.AttributeSet;
public class TextInputEditTextSuffix extends TextInputEditText {
private TextPaint textPaint = new TextPaint();
private String suffix = "";
public TextInputEditTextSuffix(Context context) {
super(context);
}
public TextInputEditTextSuffix(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TextInputEditTextSuffix(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(!getText().toString().equals(""))
{
int suffixXPosition = (int) textPaint.measureText(getText().toString() + getPaddingLeft());
canvas.drawText(suffix, Math.max(suffixXPosition, 0), getBaseline(), textPaint);
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
textPaint.setColor(getCurrentTextColor());
textPaint.setTextSize(getTextSize());
textPaint.setTextAlign(Paint.Align.LEFT);
}
public void setSuffix(String suffix)
{
this.suffix = suffix;
}
}

View File

@ -0,0 +1,250 @@
package com.herbron.moodl.DataManagers;
import com.herbron.moodl.Activities.HomeActivity;
import com.herbron.moodl.DataManagers.CurrencyData.Trade;
import com.herbron.moodl.DataNotifiers.BinanceUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.ExchangeManager.BinanceManager;
import com.herbron.moodl.DataManagers.ExchangeManager.HitBtcManager;
import com.herbron.moodl.DataNotifiers.BalanceUpdateNotifierInterface;
import com.herbron.moodl.DataNotifiers.HitBTCUpdateNotifierInterface;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Tiji on 25/12/2017.
*/
public class BalanceManager implements BinanceUpdateNotifierInterface, HitBTCUpdateNotifierInterface {
private List<Currency> manualBalances;
private List<Currency> totalBalance;
private android.content.Context context;
private DatabaseManager databaseManager;
private CryptocompareApiManager cryptocompareApiManager;
private int balanceCounter;
private List<HitBtcManager> hitBtcManagers;
private List<BinanceManager> binanceManagers;
private BalanceUpdateNotifierInterface balanceUpdateNotifierInterface;
public BalanceManager(android.content.Context context)
{
this.context = context;
manualBalances = new ArrayList<Currency>();
databaseManager = new DatabaseManager(context);
hitBtcManagers = new ArrayList<>();
binanceManagers = new ArrayList<>();
cryptocompareApiManager = CryptocompareApiManager.getInstance(context);
balanceCounter = 0;
setListener((BalanceUpdateNotifierInterface) ((HomeActivity) context).getHoldingsFragment());
}
public void setListener(BalanceUpdateNotifierInterface balanceUpdateNotifierInterface)
{
this.balanceUpdateNotifierInterface = balanceUpdateNotifierInterface;
}
public void updateExchangeKeys()
{
hitBtcManagers.clear();
hitBtcManagers = databaseManager.getHitBtcAccounts(context);
binanceManagers.clear();
binanceManagers = databaseManager.getBinanceAccounts();
}
public List<Currency> getTotalBalance()
{
return totalBalance;
}
public void updateTotalBalance()
{
boolean isUpdated = false;
updateExchangeKeys();
balanceCounter = 0;
manualBalances = databaseManager.getAllCurrenciesFromTransactions();
if(binanceManagers.size() > 0)
{
isUpdated = true;
for(int i = 0; i < binanceManagers.size(); i++)
{
BinanceManager binanceManager = binanceManagers.get(i);
binanceManager.addListener(this);
binanceManager.updateBalance();
}
}
if(hitBtcManagers.size() > 0)
{
isUpdated = true;
for(int i = 0; i < hitBtcManagers.size(); i++)
{
final HitBtcManager hitBtcManager = hitBtcManagers.get(i);
hitBtcManager.addListener(this);
hitBtcManager.updateGlobalBalance();
}
}
if(!isUpdated)
{
refreshAllBalances();
}
}
private void countBalances()
{
balanceCounter++;
if(balanceCounter == hitBtcManagers.size() + binanceManagers.size())
{
refreshAllBalances();
balanceCounter = 0;
}
}
private void refreshAllBalances()
{
totalBalance = new ArrayList<>();
for(int i = 0; i < hitBtcManagers.size(); i++)
{
mergeBalanceTotal(hitBtcManagers.get(i).getBalance());
}
for(int i = 0; i < binanceManagers.size(); i++)
{
mergeBalanceTotal(binanceManagers.get(i).getBalance());
}
mergeBalanceTotal(manualBalances);
balanceUpdateNotifierInterface.onBalanceDataUpdated();
}
private void mergeBalanceTotal(List<Currency> balance)
{
if(balance != null)
{
for(int i = 0; i < balance.size(); i++)
{
boolean isIn = false;
for(int j = 0; j < totalBalance.size(); j++)
{
if(balance.get(i).getSymbol().equals(totalBalance.get(j).getSymbol()))
{
totalBalance.get(j).setBalance(totalBalance.get(j).getBalance() + balance.get(i).getBalance());
isIn = true;
}
}
if(!isIn)
{
totalBalance.add(balance.get(i));
}
}
}
}
@Override
public void onBinanceTradesUpdated(List<Trade> trades) {
}
@Override
public void onBinanceBalanceUpdateSuccess() {
countBalances();
}
@Override
public void onBinanceBalanceUpdateError(int accountId, String error) {
databaseManager.disableExchangeAccount(accountId);
balanceUpdateNotifierInterface.onBalanceError(error);
}
@Override
public void onHitBTCBalanceUpdateSuccess() {
countBalances();
}
@Override
public void onHitBTCBalanceUpdateError(int accountId, String error) {
databaseManager.disableExchangeAccount(accountId);
balanceUpdateNotifierInterface.onBalanceError(error);
}
public void sortCoins()
{
for(int i = 0; i < totalBalance.size(); i++)
{
for(int j = i; j < totalBalance.size(); j++)
{
if(totalBalance.get(j).getBalance() * totalBalance.get(j).getValue() > totalBalance.get(i).getBalance() * totalBalance.get(i).getValue())
{
Currency temp = totalBalance.get(j);
totalBalance.set(j, totalBalance.get(i));
totalBalance.set(i, temp);
}
}
}
}
public CryptocompareApiManager getCryptocompareApiManager()
{
return cryptocompareApiManager;
}
public String getCurrencyName(String symbol)
{
String currencyName = null;
try {
JSONObject jsonObject = new JSONObject(cryptocompareApiManager.getCoinInfosHashmap().get(symbol));
currencyName = jsonObject.getString("CoinName");
} catch (JSONException e) {
e.printStackTrace();
} catch (NullPointerException e) {
currencyName = symbol;
}
return currencyName;
}
public int getCurrencyId(String symbol)
{
int id = 0;
try {
JSONObject jsonObject = new JSONObject(cryptocompareApiManager.getCoinInfosHashmap().get(symbol));
id = jsonObject.getInt("Id");
} catch (JSONException e) {
e.printStackTrace();
} catch (NullPointerException e) {
id = -1;
}
return id;
}
}

View File

@ -1,12 +1,11 @@
package com.nauk.coinfolio.DataManagers.CurrencyData;
package com.herbron.moodl.DataManagers.CurrencyData;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import com.herbron.moodl.CurrencyInfoUpdateNotifierInterface;
import java.lang.reflect.Field;
import java.util.ArrayList;
@ -19,7 +18,7 @@ import java.util.List;
public class Currency implements Parcelable {
private int id;
private String tickerId;
private int tickerId;
private String name;
private String symbol;
private double value;
@ -39,11 +38,17 @@ public class Currency implements Parcelable {
private String proofType;
private int totalSupply;
private double marketCapitalization;
private double volume24h;
private double dominance;
private int rank;
private String startDate;
private List<String> socialMediaLinks;
private List<OnTimestampPriceUpdatedListener> onTimestampPriceUpdatedListenerList;
//private String proofType
private CurrencyInfoUpdateNotifierInterface currencyInfoUpdateNotifierInterface;
public Currency() {}
public Currency(String symbol, double balance)
@ -65,9 +70,19 @@ public class Currency implements Parcelable {
this.symbol = symbol;
}
//public Currency(int id, String symbol, String name, String algorithm, String proofType, )
public Currency(String name, String symbol, int tickerId)
{
this.name = name;
this.symbol = symbol;
this.tickerId = tickerId;
}
public void getTimestampPrice(android.content.Context context, String toSymbol, final PriceCallBack callBack, long timestamp)
public void setListener(CurrencyInfoUpdateNotifierInterface currencyInfoUpdateNotifierInterface)
{
this.currencyInfoUpdateNotifierInterface = currencyInfoUpdateNotifierInterface;
}
public void getTimestampPrice(android.content.Context context, String toSymbol, long timestamp)
{
dataRetriver = new CurrencyDataRetriever(context);
@ -77,30 +92,20 @@ public class Currency implements Parcelable {
@Override
public void onSuccess(String price) {
callBack.onSuccess(price);
currencyInfoUpdateNotifierInterface.onTimestampPriceUpdated(price);
if(onTimestampPriceUpdatedListenerList != null)
{
for(int i = 0; i < onTimestampPriceUpdatedListenerList.size(); i++)
{
onTimestampPriceUpdatedListenerList.get(i).onTimeStampPriceUpdated(price);
}
}
}
}, timestamp);
}
public static String getIconUrl(String currencyDetails)
{
String url;
try {
JSONObject jsonObject = new JSONObject(currencyDetails);
url = "https://www.cryptocompare.com" + jsonObject.getString("ImageUrl") + "?width=50";
} catch (NullPointerException e) {
//Log.d(context.getResources().getString(R.string.debug), symbol + " has no icon URL");
url = null;
} catch (JSONException e) {
//Log.d(context.getResources().getString(R.string.debug), "Url parsing error for " + symbol);
url = null;
}
return url;
}
public void updatePrice(android.content.Context context, String toSymbol, final CurrencyCallBack callBack)
public void updatePrice(android.content.Context context, String toSymbol, final CurrencyInfoUpdateNotifierInterface callBack)
{
dataRetriver = new CurrencyDataRetriever(context);
@ -114,12 +119,12 @@ public class Currency implements Parcelable {
setDayFluctuationPercentage(currencyInfo.getDayFluctuationPercentage());
}
callBack.onSuccess(Currency.this);
callBack.onPriceUpdated(currencyInfo);
}
});
}
public void updateHistoryMinutes(android.content.Context context, String toSymbol, final CurrencyCallBack callBack)
public void updateHistoryMinutes(android.content.Context context, String toSymbol)
{
dataRetriver = new CurrencyDataRetriever(context);
@ -128,7 +133,7 @@ public class Currency implements Parcelable {
public void onSuccess(List<CurrencyDataChart> dataChart) {
setHistoryMinutes(dataChart);
callBack.onSuccess(Currency.this);
currencyInfoUpdateNotifierInterface.onHistoryDataUpdated();
}
@Override
@ -185,7 +190,7 @@ public class Currency implements Parcelable {
});
}
public void updateHistoryHours(android.content.Context context, String toSymbol, final CurrencyCallBack callBack)
public void updateHistoryHours(android.content.Context context, String toSymbol)
{
dataRetriver = new CurrencyDataRetriever(context);
dataRetriver.updateHistory(symbol, toSymbol, new CurrencyDataRetriever.DataChartCallBack() {
@ -193,7 +198,7 @@ public class Currency implements Parcelable {
public void onSuccess(List<CurrencyDataChart> dataChart) {
setHistoryHours(dataChart);
callBack.onSuccess(Currency.this);
currencyInfoUpdateNotifierInterface.onHistoryDataUpdated();
}
@Override
@ -201,7 +206,7 @@ public class Currency implements Parcelable {
}, CurrencyDataRetriever.HOURS);
}
public void updateHistoryDays(android.content.Context context, String toSymbol, final CurrencyCallBack callBack)
public void updateHistoryDays(android.content.Context context, String toSymbol)
{
dataRetriver = new CurrencyDataRetriever(context);
dataRetriver.updateHistory(symbol, toSymbol, new CurrencyDataRetriever.DataChartCallBack() {
@ -209,7 +214,7 @@ public class Currency implements Parcelable {
public void onSuccess(List<CurrencyDataChart> dataChart) {
setHistoryDays(dataChart);
callBack.onSuccess(Currency.this);
currencyInfoUpdateNotifierInterface.onHistoryDataUpdated();
}
@Override
@ -217,10 +222,17 @@ public class Currency implements Parcelable {
}, CurrencyDataRetriever.DAYS);
}
public void updateDetails(android.content.Context context, final CurrencyCallBack callBack)
private int getDarkenColor(int color)
{
dataRetriver = new CurrencyDataRetriever(context);
int transColor;
int alpha = Color.alpha(color);
int r = Math.round(Color.red(color) * 0.8f);
int g = Math.round(Color.green(color) * 0.8f);
int b = Math.round(Color.blue(color) * 0.8f);
transColor = Color.argb(alpha, r, g, b);
return transColor ;
}
public void setId(int id)
@ -235,9 +247,24 @@ public class Currency implements Parcelable {
public void setChartColor(int chartColor)
{
double lightness = 1 - (0.299 * Color.red(chartColor) + 0.587 * Color.green(chartColor) + 0.114 * Color.blue(chartColor)) / 255;
if(lightness < 0.1)
{
chartColor = getDarkenColor(chartColor);
}
this.chartColor = chartColor;
}
public double getVolume24h() {
return volume24h;
}
public void setVolume24h(double volume24h) {
this.volume24h = volume24h;
}
public int getChartColor()
{
return chartColor;
@ -397,11 +424,11 @@ public class Currency implements Parcelable {
this.rank = rank;
}
public String getTickerId() {
public int getTickerId() {
return tickerId;
}
public void setTickerId(String tickerId) {
public void setTickerId(int tickerId) {
this.tickerId = tickerId;
}
@ -413,6 +440,11 @@ public class Currency implements Parcelable {
this.startDate = startDate;
}
public float getDominance(float totalMarketCapitalization)
{
return (float) (marketCapitalization / totalMarketCapitalization) * 100;
}
private void updateDayFluctuation()
{
if(historyMinutes != null)
@ -470,7 +502,7 @@ public class Currency implements Parcelable {
dest.writeList(this.historyMinutes);
dest.writeParcelable(this.icon, flags);
dest.writeInt(this.chartColor);
dest.writeString(this.tickerId);
dest.writeInt(this.tickerId);
}
protected Currency(Parcel in) {
@ -485,7 +517,7 @@ public class Currency implements Parcelable {
in.readList(this.historyMinutes, CurrencyDataChart.class.getClassLoader());
this.icon = in.readParcelable(Bitmap.class.getClassLoader());
this.chartColor = in.readInt();
this.tickerId = in.readString();
this.tickerId = in.readInt();
}
public static final Parcelable.Creator<Currency> CREATOR = new Parcelable.Creator<Currency>() {
@ -499,4 +531,19 @@ public class Currency implements Parcelable {
return new Currency[size];
}
};
public interface OnTimestampPriceUpdatedListener
{
void onTimeStampPriceUpdated(String price);
}
public void addOnTimestampPriceUpdatedListener(OnTimestampPriceUpdatedListener onTimestampPriceUpdatedListener)
{
if(onTimestampPriceUpdatedListenerList == null)
{
onTimestampPriceUpdatedListenerList = new ArrayList<>();
}
onTimestampPriceUpdatedListenerList.add(onTimestampPriceUpdatedListener);
}
}

View File

@ -0,0 +1,445 @@
package com.herbron.moodl.DataManagers.CurrencyData;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.herbron.moodl.Activities.CurrencyDetailsActivity;
import com.herbron.moodl.CurrencyInfoUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.DatabaseManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import com.herbron.moodl.MoodlBox;
import com.herbron.moodl.Utils.PlaceholderUtils;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.List;
import static com.herbron.moodl.MoodlBox.collapseH;
import static com.herbron.moodl.MoodlBox.expandH;
import static com.herbron.moodl.MoodlBox.getIconDominantColor;
import static com.herbron.moodl.MoodlBox.numberConformer;
/**
* Created by Tiji on 12/05/2018.
*/
public class CurrencyCardview extends CardView implements CurrencyInfoUpdateNotifierInterface {
private static final int FADE_IN_DURATION = 300;
private Currency currency;
private Activity parentActivity;
private Context context;
private OnClickListener detailsClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(parentActivity, CurrencyDetailsActivity.class);
intent.putExtra(getContext().getString(R.string.currency), currency);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(parentActivity, findViewById(R.id.LineChartView), "chart");
parentActivity.startActivity(intent, activityOptions.toBundle());
}
else {
parentActivity.startActivity(intent);
}
}
};
public CurrencyCardview(@NonNull Context context) {
super(context);
this.context = context;
}
public CurrencyCardview(@NonNull final Context context, final Currency currency, final Activity activity)
{
super (context);
currency.setListener(this);
this.currency = currency;
this.parentActivity = activity;
this.context = context;
LayoutInflater.from(context).inflate(R.layout.cardview_watchlist, this, true);
((LineChart) findViewById(R.id.LineChartView)).setNoDataTextColor(currency.getChartColor());
setupCardView();
setOnClickListeners();
updateCardviewInfos();
findViewById(R.id.deleteCardWatchlist).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
DatabaseManager databaseManager = new DatabaseManager(getContext());
databaseManager.deleteCurrencyFromWatchlist(currency.getSymbol());
collapseH(CurrencyCardview.this);
}
});
updateColor();
startIconUpdater();
}
public CurrencyCardview(@NonNull final Context context, final Currency currency, Activity activity, boolean isBalanceHidden)
{
super(context);
currency.setListener(this);
this.currency = currency;
this.parentActivity = activity;
this.context = context;
LayoutInflater.from(context).inflate(R.layout.cardview_currency, this, true);
((LineChart) findViewById(R.id.LineChartView)).setNoDataTextColor(currency.getChartColor());
setupCardView();
setOnClickListeners();
updateCardviewInfos();
updateColor();
startIconUpdater();
}
private void startIconUpdater()
{
IconDownloader iconDownloader = new IconDownloader();
iconDownloader.execute(context, currency);
iconDownloader.setOnBitmapDownloadedListener(new IconDownloader.OnBitmapDownloadedListener() {
@Override
public void onDownloaded(Bitmap icon) {
currency.setIcon(icon);
currency.setChartColor(getIconDominantColor(context, icon));
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
updateCurrencyColorRelatedLayouts();
}
});
}
});
}
private void updateCurrencyColorRelatedLayouts()
{
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new AccelerateInterpolator());
fadeIn.setDuration(FADE_IN_DURATION);
ImageView currencyIconImageView = findViewById(R.id.currencyIcon);
currencyIconImageView.setImageBitmap(currency.getIcon());
currencyIconImageView.startAnimation(fadeIn);
Drawable arrowDrawable = ((ImageView) findViewById(R.id.detailsArrow)).getDrawable();
arrowDrawable.mutate();
arrowDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
arrowDrawable.invalidateSelf();
Drawable progressDrawable = ((ProgressBar) findViewById(R.id.progressBarLinechart)).getIndeterminateDrawable();
progressDrawable.mutate();
progressDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
progressDrawable.invalidateSelf();
if(findViewById(R.id.currencyPortfolioDominance) != null)
{
Drawable progressBarDrawable = ((ProgressBar) findViewById(R.id.currencyPortfolioDominance)).getProgressDrawable();
progressBarDrawable.mutate();
progressBarDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
progressBarDrawable.invalidateSelf();
}
LineChart lineChart = findViewById(R.id.LineChartView);
if(currency.getHistoryMinutes() != null)
{
lineChart.setData(generateData());
lineChart.invalidate();
}
}
private void setOnClickListeners()
{
setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
PreferencesManager preferencesManager = new PreferencesManager(context);
if (view.findViewById(R.id.collapsableLayout).getVisibility() == View.VISIBLE) {
collapseH(view.findViewById(R.id.collapsableLayout));
} else {
view.findViewById(R.id.linearLayoutSubCharts).setVisibility(View.GONE);
view.findViewById(R.id.progressBarLinechart).setVisibility(View.VISIBLE);
expandH(view.findViewById(R.id.collapsableLayout));
if (currency.getHistoryMinutes() == null) {
currency.updateHistoryMinutes(context, preferencesManager.getDefaultCurrency());
}
else
{
expandH(view.findViewById(R.id.collapsableLayout));
view.findViewById(R.id.progressBarLinechart).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubCharts).setVisibility(View.VISIBLE);
}
}
}
});
findViewById(R.id.linearLayoutSubCharts).setOnClickListener(detailsClickListener);
findViewById(R.id.LineChartView).setOnClickListener(detailsClickListener);
}
public Currency getCurrency()
{
return currency;
}
private void setupCardView()
{
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.MarginLayoutParams.MATCH_PARENT, LinearLayout.MarginLayoutParams.WRAP_CONTENT);
int margin = (int) MoodlBox.convertDpToPx(10, getResources());
layoutParams.setMargins(margin, margin, margin, 0);
setLayoutParams(layoutParams);
setRadius(MoodlBox.convertDpToPx(2, getResources()));
setClickable(false);
setFocusable(false);
setCardBackgroundColor(MoodlBox.getColor(R.color.white, getContext()));
}
private void setupLineChart(final Currency currency)
{
LineChart lineChart = findViewById(R.id.LineChartView);
lineChart.setDrawGridBackground(false);
lineChart.setDrawBorders(false);
lineChart.setDrawMarkers(false);
lineChart.setDoubleTapToZoomEnabled(false);
lineChart.setPinchZoom(false);
lineChart.setScaleEnabled(false);
lineChart.setDragEnabled(false);
lineChart.getDescription().setEnabled(false);
lineChart.getAxisLeft().setEnabled(false);
lineChart.getAxisRight().setEnabled(false);
lineChart.getLegend().setEnabled(false);
lineChart.getXAxis().setEnabled(false);
lineChart.setViewPortOffsets(0, 0, 0, 0);
lineChart.setData(generateData());
}
private void updateCardviewInfos()
{
((TextView) findViewById(R.id.currencyFluctuationTextView))
.setText(PlaceholderUtils.getValueParenthesisString(numberConformer(currency.getDayFluctuation()), getContext()));
((TextView) findViewById(R.id.currencyValueTextView))
.setText(PlaceholderUtils.getValueString(numberConformer(currency.getValue()), getContext()));
((TextView) findViewById(R.id.currencyNameTextView))
.setText(currency.getName());
((TextView) findViewById(R.id.currencySymbolTextView))
.setText(PlaceholderUtils.getSymbolString(currency.getSymbol(), getContext()));
((TextView) findViewById(R.id.currencyFluctuationPercentageTextView))
.setText(PlaceholderUtils.getPercentageString(numberConformer(currency.getDayFluctuationPercentage()), getContext()));
}
public void updateOwnedValues(float totalValue, boolean isBalanceHidden)
{
double value = currency.getValue() * currency.getBalance();
double percentage = value / totalValue * 100;
((TextView) findViewById(R.id.currencyValueOwnedTextView))
.setText(PlaceholderUtils.getValueParenthesisString(numberConformer(currency.getValue() * currency.getBalance()), getContext()));
((TextView) findViewById(R.id.currencyOwnedTextView))
.setText(PlaceholderUtils.getBalanceString(numberConformer(currency.getBalance()), currency.getSymbol(), getContext()));
((ProgressBar) findViewById(R.id.currencyPortfolioDominance)).setProgress((int) Math.round(percentage));
((TextView) findViewById(R.id.percentageOwnedTextView)).setText(PlaceholderUtils.getPercentageString(numberConformer(percentage), getContext()));
if(isBalanceHidden)
{
findViewById(R.id.currencyPortfolioDominance).setVisibility(View.VISIBLE);
findViewById(R.id.percentageOwnedTextView).setVisibility(View.VISIBLE);
findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.GONE);
}
else
{
findViewById(R.id.currencyPortfolioDominance).setVisibility(View.INVISIBLE);
findViewById(R.id.percentageOwnedTextView).setVisibility(View.GONE);
findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.VISIBLE);
}
}
private LineData generateData()
{
LineDataSet dataSet;
List<CurrencyDataChart> dataChartList = currency.getHistoryMinutes();
ArrayList<Entry> values = new ArrayList<>();
for(int i = 0; i < dataChartList.size(); i+=10)
{
values.add(new Entry(i, (float) dataChartList.get(i).getOpen()));
}
dataSet = new LineDataSet(values, "");
dataSet.setDrawIcons(false);
dataSet.setColor(currency.getChartColor());
dataSet.setFillColor(getColorWithAplha(currency.getChartColor(), 0.5f));
dataSet.setLineWidth(1);
dataSet.setDrawFilled(true);
dataSet.setFormLineWidth(1);
dataSet.setFormSize(15);
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setHighlightEnabled(false);
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
return new LineData(dataSet);
}
private void updateColor()
{
if(currency.getDayFluctuationPercentage() >= 0)
{
((TextView) findViewById(R.id.currencyFluctuationPercentageTextView))
.setTextColor(ContextCompat.getColor(getContext(), R.color.increase));
((TextView) findViewById(R.id.currencyFluctuationTextView))
.setTextColor(ContextCompat.getColor(getContext(), R.color.increase));
}
else
{
((TextView) findViewById(R.id.currencyFluctuationPercentageTextView))
.setTextColor(ContextCompat.getColor(getContext(), R.color.decrease));
((TextView) findViewById(R.id.currencyFluctuationTextView))
.setTextColor(ContextCompat.getColor(getContext(), R.color.decrease));
}
}
private int getColorWithAplha(int color, float ratio)
{
int transColor;
int alpha = Math.round(Color.alpha(color) * ratio);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
transColor = Color.argb(alpha, r, g, b);
return transColor ;
}
@Override
public void onTimestampPriceUpdated(String price) {
}
@Override
public void onHistoryDataUpdated() {
View progressView = findViewById(R.id.progressBarLinechart);
progressView.setVisibility(View.GONE);
findViewById(R.id.linearLayoutSubCharts).setVisibility(View.VISIBLE);
if(currency.getHistoryMinutes() != null)
{
setupLineChart(currency);
}
}
@Override
public void onPriceUpdated(Currency currency) {
}
private static class IconDownloader extends AsyncTask<Object, Integer, Void> implements MoodlboxNotifierInterface
{
private Bitmap icon = null;
private OnBitmapDownloadedListener onBitmapDownloadedListener;
public Bitmap getIcon()
{
return icon;
}
public void setOnBitmapDownloadedListener(OnBitmapDownloadedListener onBitmapDownloadedListener) {
this.onBitmapDownloadedListener = onBitmapDownloadedListener;
}
@Override
protected Void doInBackground(Object... objects) {
Context context = (Context) objects[0];
Currency currency = (Currency) objects[1];
CryptocompareApiManager cryptocompareApiManager = CryptocompareApiManager.getInstance(context);
String iconUrl = MoodlBox.getIconUrl(currency.getSymbol(), cryptocompareApiManager);
if(iconUrl != null)
{
MoodlBox.getBitmapFromURL(iconUrl, currency.getSymbol(), context.getResources(), context, this);
}
return null;
}
@Override
public void onBitmapDownloaded(Bitmap bitmap) {
icon = bitmap;
onBitmapDownloadedListener.onDownloaded(bitmap);
}
public interface OnBitmapDownloadedListener {
void onDownloaded(Bitmap icon);
}
}
}

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio.DataManagers.CurrencyData;
package com.herbron.moodl.DataManagers.CurrencyData;
import android.os.Parcel;
import android.os.Parcelable;

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio.DataManagers.CurrencyData;
package com.herbron.moodl.DataManagers.CurrencyData;
import android.util.Log;
@ -8,9 +8,9 @@ import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.nauk.coinfolio.R;
import com.herbron.moodl.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -28,12 +28,12 @@ public class CurrencyDataRetriever {
final static int HOURS = 1;
final static int DAYS = 2;
private String minuteHistoryUrl = "https://min-api.cryptocompare.com/data/histominute";
private String hourHistoryUrl = "https://min-api.cryptocompare.com/data/histohour";
private String dayHistoryUrl = "https://min-api.cryptocompare.com/data/histoday";
private String priceUrl = "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=";
private String snapshotUrl = "https://www.cryptocompare.com/api/data/coinsnapshotfullbyid/?id=";
private String tickerUrl = "https://api.coinmarketcap.com/v1/ticker/";
private final static String minuteHistoryUrl = "https://min-api.cryptocompare.com/data/histominute";
private final static String hourHistoryUrl = "https://min-api.cryptocompare.com/data/histohour";
private final static String dayHistoryUrl = "https://min-api.cryptocompare.com/data/histoday";
private final static String priceUrl = "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=";
private final static String snapshotUrl = "https://www.cryptocompare.com/api/data/coinsnapshotfullbyid/?id=";
private final static String tickerUrl = "https://api.coinmarketcap.com/v2/ticker/";
private RequestQueue requestQueue;
@ -46,9 +46,9 @@ public class CurrencyDataRetriever {
requestQueue = Volley.newRequestQueue(context);
}
public void updateTickerInfos(String currencyName, final String toSymbol, final CurrencyCallBack callBack)
public void updateTickerInfos(int tickerId, final String toSymbol, final CurrencyCallBack callBack)
{
final String requestUrl = tickerUrl + currencyName + "/?convert=" + toSymbol;
final String requestUrl = tickerUrl + tickerId + "/?convert=" + toSymbol;
StringRequest stringRequest = new StringRequest(Request.Method.GET, requestUrl,
new Response.Listener<String>() {
@ -71,13 +71,15 @@ public class CurrencyDataRetriever {
{
Currency currency = new Currency();
response = response.substring(1, response.length()-1);
try {
JSONObject jsonObject = new JSONObject(response);
JSONObject currencyJsonObject = jsonObject.getJSONObject("data");
JSONObject quotesJsonObject = currencyJsonObject.getJSONObject("quotes");
JSONObject valuesJsonObject = quotesJsonObject.getJSONObject(toSymbol);
currency.setMarketCapitalization(valuesJsonObject.getDouble("market_cap"));
currency.setRank(currencyJsonObject.getInt("rank"));
currency.setMarketCapitalization(jsonObject.getDouble("market_cap_" + toSymbol.toLowerCase()));
currency.setRank(jsonObject.getInt("rank"));
} catch (JSONException e) {
e.printStackTrace();
}
@ -135,7 +137,7 @@ public class CurrencyDataRetriever {
return result;
}
public void updateHistory(final String symbolCurrencyFrom, String symbolCyrrencyTo, final DataChartCallBack callBack, int timeUnit)
void updateHistory(final String symbolCurrencyFrom, String symbolCyrrencyTo, final DataChartCallBack callBack, int timeUnit)
{
String requestUrl = getRequestUrl(timeUnit, symbolCurrencyFrom, symbolCyrrencyTo);
@ -156,8 +158,12 @@ public class CurrencyDataRetriever {
requestQueue.add(stringRequest);
}
public void updatePrice(final String symbolCurrencyFrom, String symbolCurrencyTo, final CurrencyCallBack callBack)
void updatePrice(String symbolCurrencyFrom, String symbolCurrencyTo, final CurrencyCallBack callBack)
{
if(symbolCurrencyFrom.equals("MIOTA"))
{
symbolCurrencyFrom = "IOT";
}
String requestUrl = priceUrl + symbolCurrencyFrom + "&tsyms=" + symbolCurrencyTo;
StringRequest stringRequest = new StringRequest(Request.Method.GET, requestUrl,
@ -181,6 +187,11 @@ public class CurrencyDataRetriever {
{
String requestUrl = null;
if(symbolCurrencyFrom.equals("MIOTA"))
{
symbolCurrencyFrom = "IOT";
}
switch (timeUnit)
{
case MINUTES:
@ -257,35 +268,25 @@ public class CurrencyDataRetriever {
{
List<CurrencyDataChart> dataChart = new ArrayList<>();
if(response.length() > 250)
{
response = response.substring(response.indexOf("Data\":[{") + 7, response.lastIndexOf("}],\"TimeTo"));
String[] tab = response.split(Pattern.quote("},{"));
for(int i = 0; i < tab.length; i++)
try {
JSONObject mainJsonObject = new JSONObject(response);
if(mainJsonObject.getString("Response").equals("Success"))
{
JSONArray dataJsonArray = mainJsonObject.getJSONArray("Data");
if(i == 0)
for(int i = 0; i < dataJsonArray.length(); i++)
{
tab[i] = tab[i] + "}";
}
else
{
tab[i] = "{" + tab[i] + "}";
}
try {
JSONObject jsonObject = new JSONObject(tab[i]);
dataChart.add(parseJSON(jsonObject));
} catch (JSONException e) {
Log.d(context.getResources().getString(R.string.debug_volley), "API Request error: " + e + " index: " + i);
JSONObject timeJsonObject = dataJsonArray.getJSONObject(i);
dataChart.add(parseJSON(timeJsonObject));
}
}
}
else
{
dataChart = null;
else
{
dataChart = null;
}
} catch (JSONException e) {
Log.d("moodl", "API Request error : " + e);
}
return dataChart;
@ -304,61 +305,6 @@ public class CurrencyDataRetriever {
return new CurrencyDataChart(timestamp, close, high, low, open, volumeFrom, volumeTo);
}
public void getPriceTimestamp(String symbolCurrencyFrom, final DataChartCallBack callBack, long timestamp)
{
getPriceTimestamp(symbolCurrencyFrom, "USD", callBack, timestamp);
}
public void updateHistory(String symbolCurrencyFrom, final DataChartCallBack callBack, int timeUnit)
{
if(symbolCurrencyFrom.equals("USD"))
{
callBack.onSuccess((List<CurrencyDataChart>) null);
}
else
{
updateHistory(symbolCurrencyFrom, "USD", callBack, timeUnit);
}
}
public void updatePrice(String symbolCurrencyFrom, final CurrencyCallBack callBack)
{
if(symbolCurrencyFrom.equals("USD"))
{
callBack.onSuccess(null);
}
else
{
updatePrice(symbolCurrencyFrom, "USD", callBack);
}
}
/*public void updateCryptocompareDetails(int id, final Currency.CurrencyCallBack callBack)
{
String requestUrl = getRequestUrl(timeUnit, symbolCurrencyFrom, symbolCyrrencyTo);
StringRequest stringRequest = new StringRequest(Request.Method.GET, requestUrl,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
callBack.onSuccess();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
callBack.onSuccess();
}
});
requestQueue.add(stringRequest);
}*/
public void updateCoinMarketCapDetails()
{
}
public interface DataChartCallBack {
void onSuccess(List<CurrencyDataChart> dataChart);
void onSuccess(String price);

View File

@ -0,0 +1,43 @@
package com.herbron.moodl.DataManagers.CurrencyData;
/**
* Created by Guitoune on 24/04/2018.
*/
public class Trade extends com.binance.api.client.domain.account.Trade {
private String symbol;
private String pairSymbol;
public Trade(String symbol, String pairSymbol, com.binance.api.client.domain.account.Trade biTrade)
{
this.symbol = symbol;
this.pairSymbol = pairSymbol;
setId(biTrade.getId());
setPrice(biTrade.getPrice());
setQty(biTrade.getQty());
setCommission(biTrade.getCommission());
setCommissionAsset(biTrade.getCommissionAsset());
setTime(biTrade.getTime());
setBuyer(biTrade.isBuyer());
setMaker(biTrade.isMaker());
setBestMatch(biTrade.isBestMatch());
setOrderId(biTrade.getOrderId());
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getPairSymbol() {
return pairSymbol;
}
public void setPairSymbol(String pairSymbol) {
this.pairSymbol = pairSymbol;
}
}

View File

@ -0,0 +1,156 @@
package com.herbron.moodl.DataManagers.CurrencyData;
/**
* Created by Guitoune on 30/01/2018.
*/
public class Transaction {
private int transactionId;
private String symbol;
private double amount;
private long timestamp;
private double price;
private double fees;
private String feeCurrency;
private String feeFormat;
private String note;
private String symPair;
private String source;
private String destination;
private String type;
private boolean isDeducted;
public Transaction(int transactionId, String symbol, String symPair, double amount, long timestamp, double purchasedPrice, double fees, String note, String feeCurrency, String source, String destination, String type, String feeFormat, boolean isDeducted)
{
this.transactionId = transactionId;
this.symbol = symbol;
this.symPair = symPair;
this.amount = amount;
this.timestamp = timestamp;
this.price = purchasedPrice;
this.fees = fees;
this.note = note;
this.feeCurrency = feeCurrency;
this.source = source;
this.destination = destination;
this.type = type;
this.feeFormat = feeFormat;
this.isDeducted = isDeducted;
}
public int getTransactionId() {
return transactionId;
}
public void setTransactionId(int transactionId) {
this.transactionId = transactionId;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public double getAmount() {
return amount;
}
public long getTimestamp()
{
return timestamp;
}
public void setAmount(double amount) {
this.amount = amount;
}
public void setPrice(double purchasedPrice)
{
this.price = purchasedPrice;
}
public double getPrice()
{
return price;
}
public double getFees() {
return fees;
}
public void setFees(double fees) {
this.fees = fees;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getSymPair() {
return symPair;
}
public void setSymPair(String symPair) {
this.symPair = symPair;
}
public String getFeeCurrency() {
return feeCurrency;
}
public void setFeeCurrency(String feeCurrency) {
this.feeCurrency = feeCurrency;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getFeeFormat() {
return feeFormat;
}
public void setFeeFormat(String feeFormat) {
this.feeFormat = feeFormat;
}
public boolean isDeducted() {
return isDeducted;
}
public void setDeducted(boolean deducted) {
isDeducted = deducted;
}
}

View File

@ -0,0 +1,91 @@
package com.herbron.moodl.DataManagers;
import android.content.Context;
import android.util.Log;
import com.herbron.moodl.R;
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class DataCrypter {
private static Key aesKey;
public static void updateKey(String key)
{
try {
byte[] keyByte = key.getBytes("UTF-8");
byte[] finalKey = new byte[32];
System.arraycopy(keyByte, 0, finalKey, 0, keyByte.length);
aesKey = new SecretKeySpec(finalKey, "AES");
} catch (UnsupportedEncodingException e) {
Log.d("moodl", "Error while creating encryption key " + e.getMessage());
}
}
public static String encrypt(Context context, String data)
{
String encryptedData = null;
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(context.getString(R.string.ivKey).getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivParameterSpec);
byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
encryptedData = Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | UnsupportedEncodingException
| InvalidAlgorithmParameterException e) {
Log.d("moodl", "Error while encrypting data " + e.getMessage());
}
return encryptedData;
}
public static String decrypt(Context context, String data)
{
String decryptedData = null;
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(context.getString(R.string.ivKey).getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
byte[] decryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
//byte[] dataBytes = Base64.decode(data, Base64.DEFAULT);
decryptedData = new String(decryptedBytes, StandardCharsets.UTF_8);
} catch(NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | UnsupportedEncodingException
| InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return decryptedData;
}
}

View File

@ -0,0 +1,797 @@
package com.herbron.moodl.DataManagers;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.herbron.moodl.Activities.RecordTransactionFragments.TransferFragment;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Transaction;
import com.herbron.moodl.DataManagers.ExchangeManager.BinanceManager;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import com.herbron.moodl.DataManagers.ExchangeManager.HitBtcManager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.herbron.moodl.Utils.TransferUtils.isBalanceRelated;
/**
* Created by Guitoune on 14/01/2018.
*/
public class DatabaseManager extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 17;
private static final String DATABASE_NAME = "mdn.db";
public static final String TABLE_MANUAL_TRANSACTIONS = "ManualTransactions";
public static final String TABLE_EXCHANGE_KEYS = "ExchangeKeys";
public static final String TABLE_WATCHLIST = "Watchlist";
private static final String KEY_TRANSACTION_ID = "transactionId";
private static final String KEY_TRANSACTION_SYMBOL = "symbol";
private static final String KEY_TRANSACTION_AMOUNT = "amount";
private static final String KEY_TRANSACTION_PAIR = "symPair";
private static final String KEY_TRANSACTION_DATE = "transactionDate";
private static final String KEY_TRANSACTION_PURCHASE_PRICE = "purchasePrice";
private static final String KEY_TRANSACTION_SOURCE = "source";
private static final String KEY_TRANSACTION_DESTINATION = "destination";
private static final String KEY_TRANSACTION_FEES = "fees";
private static final String KEY_TRANSACTION_FEE_CURRENCY = "feeCurrency";
private static final String KEY_TRANSACTION_FEE_FORMAT = "feeFormat";
private static final String KEY_TRANSACTION_NOTES = "notes";
private static final String KEY_TRANSACTION_TYPE = "transactionType";
private static final String KEY_TRANSACTION_DEDUCT = "deductHoldings";
private static final String KEY_EXCHANGE_ID = "idExchange";
private static final String KEY_EXCHANGE_NAME = "name";
private static final String KEY_EXCHANGE_TYPE = "type";
private static final String KEY_EXCHANGE_DESCRIPTION = "description";
private static final String KEY_EXCHANGE_PUBLIC_KEY = "publicKey";
private static final String KEY_EXCHANGE_SECRET_KEY = "secretKey";
private static final String KEY_EXCHANGE_IS_ENABLED = "enabled";
private static final String KEY_WATCHLIST_ID = "idWatchlist";
private static final String KEY_WATCHLIST_SYMBOL = "symbol";
private static final String KEY_WATCHLIST_NAME = "name";
private static final String KEY_WATCHLIST_POSITION = "position";
public static final int BINANCE_TYPE = 0;
public static final int HITBTC_TYPE = 1;
public DatabaseManager(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_MANUAL_TRANSACTIONS + "("
+ KEY_TRANSACTION_ID + " INTEGER PRIMARY KEY,"
+ KEY_TRANSACTION_SYMBOL + " VARCHAR(4),"
+ KEY_TRANSACTION_AMOUNT + " TEXT,"
+ KEY_TRANSACTION_DATE + " TEXT,"
+ KEY_TRANSACTION_PURCHASE_PRICE + " REAL,"
+ KEY_TRANSACTION_NOTES + " TEXT,"
+ KEY_TRANSACTION_PAIR + " VARCHAR(4),"
+ KEY_TRANSACTION_FEE_CURRENCY + " VARCHAR(4),"
+ KEY_TRANSACTION_FEES + " REAL,"
+ KEY_TRANSACTION_FEE_FORMAT + " VARCHAR(1),"
+ KEY_TRANSACTION_SOURCE + " TEXT,"
+ KEY_TRANSACTION_DESTINATION + " TEXT,"
+ KEY_TRANSACTION_TYPE + " VARCHAR(1),"
+ KEY_TRANSACTION_DEDUCT + " INTEGER"
+ ");");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_EXCHANGE_KEYS + "("
+ KEY_EXCHANGE_ID + " INTEGER PRIMARY KEY,"
+ KEY_EXCHANGE_NAME + " TEXT,"
+ KEY_EXCHANGE_TYPE + " INTEGER,"
+ KEY_EXCHANGE_DESCRIPTION + " TEXT,"
+ KEY_EXCHANGE_PUBLIC_KEY + " TEXT,"
+ KEY_EXCHANGE_SECRET_KEY + " TEXT,"
+ KEY_EXCHANGE_IS_ENABLED + " INTEGER"
+ ");");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_WATCHLIST + "("
+ KEY_WATCHLIST_ID + " INTEGER PRIMARY KEY,"
+ KEY_WATCHLIST_SYMBOL + " VARCHAR(4),"
+ KEY_WATCHLIST_NAME + " TEXT,"
+ KEY_WATCHLIST_POSITION + " INTEGER"
+ ");");
//loadSample(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS " + TABLE_MANUAL_TRANSACTIONS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_EXCHANGE_KEYS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_WATCHLIST);
onCreate(db);
}
private boolean isCurrencyInWatchlist(String symbol)
{
String searchQuerry = "SELECT * FROM " + TABLE_WATCHLIST + " WHERE " + KEY_WATCHLIST_SYMBOL + "='" + symbol + "'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor result = db.rawQuery(searchQuerry, null);
return result.moveToFirst();
}
public boolean addCurrencyToWatchlist(Currency currency)
{
SQLiteDatabase db = this.getWritableDatabase();
if(!isCurrencyInWatchlist(currency.getSymbol()))
{
ContentValues values = new ContentValues();
values.put(KEY_WATCHLIST_SYMBOL, currency.getSymbol());
values.put(KEY_WATCHLIST_NAME, currency.getName());
values.put(KEY_WATCHLIST_POSITION, getWatchlistRowCount(db));
db.insert(TABLE_WATCHLIST, null, values);
db.close();
return true;
}
return false;
}
public void updateTransactionWithId(int transactionId, double amount, Date date, double purchasedPrice, double fees, String note, String symbolFrom, String feeCurrency, String destination, String source, String type, String feeFormat, boolean deductFromHoldings)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(KEY_TRANSACTION_AMOUNT, amount);
cv.put(KEY_TRANSACTION_DATE, date.getTime());
cv.put(KEY_TRANSACTION_PURCHASE_PRICE, purchasedPrice);
cv.put(KEY_TRANSACTION_FEES, fees);
cv.put(KEY_TRANSACTION_NOTES, note);
cv.put(KEY_TRANSACTION_PAIR, symbolFrom);
cv.put(KEY_TRANSACTION_FEE_CURRENCY, feeCurrency);
cv.put(KEY_TRANSACTION_SOURCE, source);
cv.put(KEY_TRANSACTION_DESTINATION, destination);
cv.put(KEY_TRANSACTION_TYPE, type);
cv.put(KEY_TRANSACTION_FEE_FORMAT, feeFormat);
cv.put(KEY_TRANSACTION_DEDUCT, deductFromHoldings ? 1 : 0);
db.update(TABLE_MANUAL_TRANSACTIONS, cv, KEY_TRANSACTION_ID + "=" + transactionId, null);
}
public void addTransaction(String symbol, Double amount, Date date, double purchasePrice, double fees, String note, String symbolFrom, String feeCurrency, String destination, String source, String type, String feeFormat, boolean deductFromHoldings)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_TRANSACTION_SYMBOL, symbol);
values.put(KEY_TRANSACTION_AMOUNT, amount);
values.put(KEY_TRANSACTION_DATE, date.getTime());
values.put(KEY_TRANSACTION_PURCHASE_PRICE, purchasePrice);
values.put(KEY_TRANSACTION_FEES, fees);
values.put(KEY_TRANSACTION_NOTES, note);
values.put(KEY_TRANSACTION_PAIR, symbolFrom);
values.put(KEY_TRANSACTION_FEE_CURRENCY, feeCurrency);
values.put(KEY_TRANSACTION_SOURCE, source);
values.put(KEY_TRANSACTION_DESTINATION, destination);
values.put(KEY_TRANSACTION_TYPE, type);
values.put(KEY_TRANSACTION_FEE_FORMAT, feeFormat);
values.put(KEY_TRANSACTION_DEDUCT, deductFromHoldings ? 1 : 0);
db.insert(TABLE_MANUAL_TRANSACTIONS, null, values);
db.close();
}
public void updateWatchlistPosition(String symbol, int position)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(KEY_WATCHLIST_POSITION, position);
db.update(TABLE_WATCHLIST, cv, KEY_WATCHLIST_SYMBOL + "='" + symbol + "'", null);
}
private int getWatchlistRowCount(SQLiteDatabase db)
{
String countQuerry = "SELECT COUNT() FROM " + TABLE_WATCHLIST;
Cursor result = db.rawQuery(countQuerry, null);
result.moveToFirst();
return result.getInt(0);
}
public int getDisabledExchangeAccountsNumber()
{
SQLiteDatabase db = this.getWritableDatabase();
String countQuerry = "SELECT COUNT() FROM " + TABLE_EXCHANGE_KEYS + " WHERE " + KEY_EXCHANGE_IS_ENABLED + "=0";
Cursor result = db.rawQuery(countQuerry, null);
result.moveToFirst();
return result.getInt(0);
}
public void deleteExchangeAccountFromId(int id)
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_EXCHANGE_KEYS, KEY_EXCHANGE_ID + " = " + id, null);
db.close();
}
public void deleteCurrencyFromWatchlist(String symbol)
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_WATCHLIST, KEY_WATCHLIST_SYMBOL + " = '" + symbol + "'", null);
db.close();
}
public void disableExchangeAccount(int id)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(KEY_EXCHANGE_IS_ENABLED, 0);
db.update(TABLE_EXCHANGE_KEYS, cv, KEY_EXCHANGE_ID + "='" + id + "'", null);
}
public Exchange getExchangeFromId(int exchangeId)
{
String selectQuerry = "SELECT * FROM " + TABLE_EXCHANGE_KEYS + " WHERE " + KEY_EXCHANGE_ID + " = " + exchangeId;
SQLiteDatabase db = this.getWritableDatabase();
Cursor result = db.rawQuery(selectQuerry, null);
Exchange selectedExchange = null;
if(result.moveToFirst())
{
selectedExchange = new Exchange(result.getInt(result.getColumnIndex(KEY_EXCHANGE_ID))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_NAME))
, result.getInt(result.getColumnIndex(KEY_EXCHANGE_TYPE))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_DESCRIPTION))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_PUBLIC_KEY))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_SECRET_KEY))
, (result.getInt(result.getColumnIndex(KEY_EXCHANGE_IS_ENABLED)) == 1));
}
return selectedExchange;
}
public ArrayList<Exchange> getExchanges()
{
String selectQuerry = "SELECT * FROM " + TABLE_EXCHANGE_KEYS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor result = db.rawQuery(selectQuerry, null);
ArrayList<Exchange> exchanges = new ArrayList<>();
while(result.moveToNext())
{
exchanges.add(new Exchange(result.getInt(result.getColumnIndex(KEY_EXCHANGE_ID))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_NAME))
, result.getInt(result.getColumnIndex(KEY_EXCHANGE_TYPE))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_DESCRIPTION))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_PUBLIC_KEY))
, result.getString(result.getColumnIndex(KEY_EXCHANGE_SECRET_KEY))
, (result.getInt(result.getColumnIndex(KEY_EXCHANGE_IS_ENABLED)) == 1)));
}
return exchanges;
}
public void addExchange(String name, int type, String description, String publicKey, String privateKey)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_EXCHANGE_NAME, name);
values.put(KEY_EXCHANGE_TYPE, type);
values.put(KEY_EXCHANGE_DESCRIPTION, description);
values.put(KEY_EXCHANGE_PUBLIC_KEY, publicKey);
values.put(KEY_EXCHANGE_SECRET_KEY, privateKey);
values.put(KEY_EXCHANGE_IS_ENABLED, 1);
db.insert(TABLE_EXCHANGE_KEYS, null, values);
db.close();
}
public JSONArray getDatabaseBackup(Context context, String table, boolean encryptData)
{
String selectQuerry = "SELECT * FROM " + table;
SQLiteDatabase db = this.getWritableDatabase();
Cursor result = db.rawQuery(selectQuerry, null);
JSONArray backupArray = new JSONArray();
while(result.moveToNext())
{
JSONObject backupObject = new JSONObject();
for(int i = 0; i < result.getColumnCount(); i++)
{
try {
if(result.getString(i) != null)
{
if(encryptData)
{
backupObject.put(result.getColumnName(i), DataCrypter.encrypt(context, result.getString(i)));
}
else
{
backupObject.put(result.getColumnName(i), result.getString(i));
}
}
else
{
backupObject.put(result.getColumnName(i), "");
}
} catch (JSONException e) {
Log.d("moodl", "Error while creating a json backup");
}
}
backupArray.put(backupObject);
}
result.close();
db.close();
return backupArray;
}
public void wipeData(String table)
{
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM "+ table);
}
public void addRawData(Context context, JSONObject rawValues, String table, boolean decrypt)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
while(rawValues.keys().hasNext())
{
String key = rawValues.keys().next();
try {
if(decrypt)
{
values.put(key, DataCrypter.decrypt(context, rawValues.getString(key)));
}
else
{
values.put(key, rawValues.getString(key));
}
} catch (JSONException e) {
Log.d("moodl", "Error while inserting " + key + " " + e.getMessage());
}
}
db.insert(table, null, values);
db.close();
}
public void addRowApiKeys(JSONObject rawValues, Context context, boolean decrypt)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
try {
if(decrypt)
{
values.put(KEY_EXCHANGE_NAME, DataCrypter.decrypt(context, rawValues.getString(KEY_EXCHANGE_NAME)));
values.put(KEY_EXCHANGE_TYPE, DataCrypter.decrypt(context, rawValues.getString(KEY_EXCHANGE_TYPE)));
values.put(KEY_EXCHANGE_DESCRIPTION, DataCrypter.decrypt(context, rawValues.getString(KEY_EXCHANGE_DESCRIPTION)));
values.put(KEY_EXCHANGE_PUBLIC_KEY, DataCrypter.decrypt(context, rawValues.getString(KEY_EXCHANGE_PUBLIC_KEY)));
values.put(KEY_EXCHANGE_SECRET_KEY, DataCrypter.decrypt(context, rawValues.getString(KEY_EXCHANGE_SECRET_KEY)));
values.put(KEY_EXCHANGE_IS_ENABLED, DataCrypter.decrypt(context, rawValues.getString(KEY_EXCHANGE_IS_ENABLED)));
}
else
{
values.put(KEY_EXCHANGE_NAME, rawValues.getString(KEY_EXCHANGE_NAME));
values.put(KEY_EXCHANGE_TYPE, rawValues.getString(KEY_EXCHANGE_TYPE));
values.put(KEY_EXCHANGE_DESCRIPTION, rawValues.getString(KEY_EXCHANGE_DESCRIPTION));
values.put(KEY_EXCHANGE_PUBLIC_KEY, rawValues.getString(KEY_EXCHANGE_PUBLIC_KEY));
values.put(KEY_EXCHANGE_SECRET_KEY, rawValues.getString(KEY_EXCHANGE_SECRET_KEY));
values.put(KEY_EXCHANGE_IS_ENABLED, rawValues.getString(KEY_EXCHANGE_IS_ENABLED));
}
} catch (JSONException e) {
Log.d("moodl", "Error while inserting api key " + e.getMessage());
}
db.insert(TABLE_EXCHANGE_KEYS, null, values);
db.close();
}
public void addRowWatchlist(JSONObject rawValues, Context context, boolean decrypt)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
try {
if(decrypt)
{
values.put(KEY_WATCHLIST_SYMBOL, DataCrypter.decrypt(context, rawValues.getString(KEY_WATCHLIST_SYMBOL)));
values.put(KEY_WATCHLIST_NAME, DataCrypter.decrypt(context, rawValues.getString(KEY_WATCHLIST_NAME)));
values.put(KEY_WATCHLIST_POSITION, DataCrypter.decrypt(context, rawValues.getString(KEY_WATCHLIST_POSITION)));
}
else
{
values.put(KEY_WATCHLIST_SYMBOL, rawValues.getString(KEY_WATCHLIST_SYMBOL));
values.put(KEY_WATCHLIST_NAME, rawValues.getString(KEY_WATCHLIST_NAME));
values.put(KEY_WATCHLIST_POSITION, rawValues.getString(KEY_WATCHLIST_POSITION));
}
} catch (JSONException e) {
Log.d("moodl", "Error while inserting watchlist " + e.getMessage());
}
db.insert(TABLE_WATCHLIST, null, values);
db.close();
}
public void addRowTransaction(JSONObject rawValues, Context context, boolean decrypt)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
try {
if(decrypt)
{
values.put(KEY_TRANSACTION_SYMBOL, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_SYMBOL)));
values.put(KEY_TRANSACTION_AMOUNT, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_AMOUNT)));
values.put(KEY_TRANSACTION_DATE, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_DATE)));
values.put(KEY_TRANSACTION_PURCHASE_PRICE, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_PURCHASE_PRICE)));
values.put(KEY_TRANSACTION_FEES, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_FEES)));
values.put(KEY_TRANSACTION_NOTES, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_NOTES)));
values.put(KEY_TRANSACTION_PAIR, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_PAIR)));
values.put(KEY_TRANSACTION_FEE_CURRENCY, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_FEE_CURRENCY)));
values.put(KEY_TRANSACTION_SOURCE, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_SOURCE)));
values.put(KEY_TRANSACTION_DESTINATION, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_DESTINATION)));
values.put(KEY_TRANSACTION_TYPE, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_TYPE)));
values.put(KEY_TRANSACTION_FEE_FORMAT, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_FEE_FORMAT)));
values.put(KEY_TRANSACTION_DEDUCT, DataCrypter.decrypt(context, rawValues.getString(KEY_TRANSACTION_DEDUCT)));
}
else
{
values.put(KEY_TRANSACTION_SYMBOL, rawValues.getString(KEY_TRANSACTION_SYMBOL));
values.put(KEY_TRANSACTION_AMOUNT, rawValues.getString(KEY_TRANSACTION_AMOUNT));
values.put(KEY_TRANSACTION_DATE, rawValues.getString(KEY_TRANSACTION_DATE));
values.put(KEY_TRANSACTION_PURCHASE_PRICE, rawValues.getDouble(KEY_TRANSACTION_PURCHASE_PRICE));
values.put(KEY_TRANSACTION_FEES, rawValues.getDouble(KEY_TRANSACTION_FEES));
values.put(KEY_TRANSACTION_NOTES, rawValues.getString(KEY_TRANSACTION_NOTES));
values.put(KEY_TRANSACTION_PAIR, rawValues.getString(KEY_TRANSACTION_PAIR));
values.put(KEY_TRANSACTION_FEE_CURRENCY, rawValues.getString(KEY_TRANSACTION_FEE_CURRENCY));
values.put(KEY_TRANSACTION_SOURCE, rawValues.getString(KEY_TRANSACTION_SOURCE));
values.put(KEY_TRANSACTION_DESTINATION, rawValues.getString(KEY_TRANSACTION_DESTINATION));
values.put(KEY_TRANSACTION_TYPE, rawValues.getString(KEY_TRANSACTION_TYPE));
values.put(KEY_TRANSACTION_FEE_FORMAT, rawValues.getString(KEY_TRANSACTION_FEE_FORMAT));
values.put(KEY_TRANSACTION_DEDUCT, rawValues.getInt(KEY_TRANSACTION_DEDUCT));
}
} catch (JSONException e) {
Log.d("moodl", "Error while inserting transaction " + e.getMessage());
}
db.insert(TABLE_MANUAL_TRANSACTIONS, null, values);
db.close();
}
public List<Currency> getAllCurrenciesFromWatchlist()
{
String searchQuerry = "SELECT * FROM " + TABLE_WATCHLIST + " ORDER BY " + KEY_WATCHLIST_POSITION + " ASC";
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultList = db.rawQuery(searchQuerry, null);
List<Currency> currencyList = new ArrayList<>();
while(resultList.moveToNext())
{
currencyList.add(new Currency(resultList.getString(resultList.getColumnIndex(KEY_WATCHLIST_NAME)), resultList.getString(resultList.getColumnIndex(KEY_WATCHLIST_SYMBOL))));
}
resultList.close();
db.close();
return currencyList;
}
public List<HitBtcManager> getHitBtcAccounts(Context context)
{
String searchQuerry = "SELECT * FROM " + TABLE_EXCHANGE_KEYS + " WHERE " + KEY_EXCHANGE_TYPE + " = " + HITBTC_TYPE + " AND " + KEY_EXCHANGE_IS_ENABLED + " = 1";
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultList = db.rawQuery(searchQuerry, null);
List<HitBtcManager> accountList = new ArrayList<>();
while(resultList.moveToNext())
{
Exchange exchange = new Exchange(resultList.getInt(resultList.getColumnIndex(KEY_EXCHANGE_ID))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_NAME))
, resultList.getInt(resultList.getColumnIndex(KEY_EXCHANGE_TYPE))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_DESCRIPTION))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_PUBLIC_KEY))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_SECRET_KEY))
, (resultList.getInt(resultList.getColumnIndex(KEY_EXCHANGE_IS_ENABLED)) == 1));
accountList.add(new HitBtcManager(context, exchange));
}
resultList.close();
db.close();
return accountList;
}
public List<BinanceManager> getBinanceAccounts()
{
String searchQuerry = "SELECT * FROM " + TABLE_EXCHANGE_KEYS + " WHERE " + KEY_EXCHANGE_TYPE + " = " + BINANCE_TYPE + " AND " + KEY_EXCHANGE_IS_ENABLED + " = 1";
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultList = db.rawQuery(searchQuerry, null);
List<BinanceManager> accountList = new ArrayList<>();
while(resultList.moveToNext())
{
Exchange exchange = new Exchange(resultList.getInt(resultList.getColumnIndex(KEY_EXCHANGE_ID))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_NAME))
, resultList.getInt(resultList.getColumnIndex(KEY_EXCHANGE_TYPE))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_DESCRIPTION))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_PUBLIC_KEY))
, resultList.getString(resultList.getColumnIndex(KEY_EXCHANGE_SECRET_KEY))
, (resultList.getInt(resultList.getColumnIndex(KEY_EXCHANGE_IS_ENABLED)) == 1));
accountList.add(new BinanceManager(exchange));
}
resultList.close();
db.close();
return accountList;
}
public List<Currency> getAllCurrenciesFromTransactions()
{
String searchQuerry = "SELECT * FROM " + TABLE_MANUAL_TRANSACTIONS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultatList = db.rawQuery(searchQuerry, null);
List<Currency> currencyList = new ArrayList<>();
while(resultatList.moveToNext())
{
String symbol = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL));
String feeSym = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_FEE_CURRENCY));
String type = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_TYPE));
if(type != null && !type.equals(""))
{
switch (type)
{
case "b":
if(symbol.equals(feeSym))
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT)) - resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))));
}
else
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))));
}
if(resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_DEDUCT)) == 1)
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_PAIR))
, -(resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_PURCHASE_PRICE))
* resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))
+ resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES)))));
}
break;
case "s":
if(symbol.equals(feeSym))
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, -resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT)) - resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))));
}
else
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, -resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))));
}
if(resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_DEDUCT)) == 1)
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_PAIR))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_PURCHASE_PRICE))
* resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))
- resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))));
}
break;
case "t":
if(isBalanceRelated(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SOURCE))) && isBalanceRelated(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_DESTINATION))))
{
if(!resultatList.isNull(resultatList.getColumnIndex(KEY_TRANSACTION_DEDUCT)))
{
if(resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_DEDUCT)) == 1)
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, -resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))));
}
else
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, -resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))));
}
}
}
else
{
if(isBalanceRelated(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SOURCE))))
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, -resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))));
}
else
{
if(isBalanceRelated(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_DESTINATION))))
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))));
}
}
}
break;
}
}
else
{
if(symbol.equals(feeSym))
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT)) - resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))));
}
else
{
currencyList.add(new Currency(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))));
}
}
}
resultatList.close();
db.close();
return currencyList;
}
public Transaction getCurrencyTransactionById(int id)
{
String searchQuerry = "SELECT * FROM " + TABLE_MANUAL_TRANSACTIONS + " WHERE " + KEY_TRANSACTION_ID + "='" + id + "'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultatList = db.rawQuery(searchQuerry, null);
Transaction transaction = null;
if(resultatList.moveToFirst())
{
transaction = new Transaction(resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_ID))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_PAIR))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))
, resultatList.getLong(resultatList.getColumnIndex(KEY_TRANSACTION_DATE))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_PURCHASE_PRICE))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_NOTES))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_FEE_CURRENCY))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SOURCE))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_DESTINATION))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_TYPE))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_FEE_FORMAT))
, resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_DEDUCT)) == 1);
}
resultatList.close();
db.close();
return transaction;
}
public ArrayList<Transaction> getCurrencyTransactionsForSymbol(String symbol)
{
String searchQuerry = "SELECT * FROM " + TABLE_MANUAL_TRANSACTIONS + " WHERE " + KEY_TRANSACTION_SYMBOL + "='" + symbol.toUpperCase()
+ "' OR " + KEY_TRANSACTION_PAIR + "='" + symbol.toUpperCase() + "' AND " + KEY_TRANSACTION_DEDUCT + "=1";
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultatList = db.rawQuery(searchQuerry, null);
ArrayList<Transaction> transactionList = new ArrayList<>();
while (resultatList.moveToNext())
{
String type = "t";
String pair = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_PAIR));
String sym = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL));
if(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SYMBOL)).equals(symbol.toUpperCase()))
{
type = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_TYPE));
}
else
{
if(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_TYPE)).equals("s"))
{
type = "b";
pair = sym;
sym = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_PAIR));
}
else
{
if(resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_TYPE)).equals("b"))
{
type = "s";
pair = sym;
sym = resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_PAIR));
}
}
}
transactionList.add(new Transaction(resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_ID))
, sym
, pair
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_AMOUNT))
, resultatList.getLong(resultatList.getColumnIndex(KEY_TRANSACTION_DATE))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_PURCHASE_PRICE))
, resultatList.getDouble(resultatList.getColumnIndex(KEY_TRANSACTION_FEES))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_NOTES))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_FEE_CURRENCY))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_SOURCE))
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_DESTINATION))
, type
, resultatList.getString(resultatList.getColumnIndex(KEY_TRANSACTION_FEE_FORMAT))
, resultatList.getInt(resultatList.getColumnIndex(KEY_TRANSACTION_DEDUCT)) == 1));
}
resultatList.close();
db.close();
return transactionList;
}
public void deleteTransactionFromId(int id)
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_MANUAL_TRANSACTIONS, KEY_TRANSACTION_ID + "=" + id, null);
db.close();
}
}

View File

@ -0,0 +1,207 @@
package com.herbron.moodl.DataManagers.ExchangeManager;
import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.BinanceApiRestClient;
import com.binance.api.client.domain.account.Account;
import com.binance.api.client.domain.account.AssetBalance;
import com.binance.api.client.domain.account.Trade;
import com.binance.api.client.exception.BinanceApiException;
import com.herbron.moodl.DataNotifiers.BinanceUpdateNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Guitoune on 26/02/2018.
*/
public class BinanceManager extends Exchange {
private List<Currency> balance;
private ArrayList<com.herbron.moodl.DataManagers.CurrencyData.Trade> trades;
private static List<String> pairSymbolList;
private List<BinanceUpdateNotifierInterface> binanceUpdateNotifierInterfaceList;
public BinanceManager(Exchange exchange)
{
super(exchange.id, exchange.name, exchange.type, exchange.description, exchange.publicKey, exchange.privateKey, exchange.isEnabled);
createPairSymbolList();
}
public void addListener(BinanceUpdateNotifierInterface binanceUpdateNotifierInterface)
{
if(binanceUpdateNotifierInterfaceList == null)
{
binanceUpdateNotifierInterfaceList = new ArrayList<>();
}
binanceUpdateNotifierInterfaceList.add(binanceUpdateNotifierInterface);
}
private void createPairSymbolList()
{
pairSymbolList = new ArrayList<>();
pairSymbolList.add("BTC");
pairSymbolList.add("ETH");
pairSymbolList.add("BNB");
pairSymbolList.add("USDT");
}
public void updateBalance()
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(publicKey, privateKey);
BinanceApiRestClient client = factory.newRestClient();
try {
Account account = client.getAccount();
List<AssetBalance> assets = account.getBalances();
balance = new ArrayList<>();
for(int i = 0; i < assets.size(); i++)
{
if(Double.parseDouble(assets.get(i).getFree()) > 0 || Double.parseDouble(assets.get(i).getLocked()) > 0)
{
//balance.add(new Currency(assets.get(i).getAsset(), Double.parseDouble(assets.get(i).getFree()) + Double.parseDouble(assets.get(i).getLocked())));
if(!assets.get(i).getAsset().equals("VEN"))
{
balance.add(new Currency(assets.get(i).getAsset(), Double.parseDouble(assets.get(i).getFree()) + Double.parseDouble(assets.get(i).getLocked())));
}
}
}
for(BinanceUpdateNotifierInterface binanceUpdateNotifierInterface : binanceUpdateNotifierInterfaceList)
{
binanceUpdateNotifierInterface.onBinanceBalanceUpdateSuccess();
}
} catch (BinanceApiException e) {
for(BinanceUpdateNotifierInterface binanceUpdateNotifierInterface : binanceUpdateNotifierInterfaceList)
{
binanceUpdateNotifierInterface.onBinanceBalanceUpdateError(id, e.getMessage());
}
}
}
public void updateTrades(String symbol)
{
trades = new ArrayList<>();
for(int i = 0; i < pairSymbolList.size(); i++)
{
if(!pairSymbolList.get(i).equals(symbol))
{
trades.addAll(updateTrades(symbol, pairSymbolList.get(i)));
}
}
for(BinanceUpdateNotifierInterface binanceUpdateNotifierInterface : binanceUpdateNotifierInterfaceList)
{
binanceUpdateNotifierInterface.onBinanceTradesUpdated(trades);
}
}
public void updateTrades(BinanceCallBack callBack, String symbol, long fromId)
{
trades = new ArrayList<>();
for(int i = 0; i < pairSymbolList.size(); i++)
{
if(!pairSymbolList.get(i).equals(symbol))
{
trades.addAll(updateTrades(symbol, pairSymbolList.get(i), fromId));
}
}
callBack.onSuccess();
}
public void updateTransactions(String symbol)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(publicKey, privateKey);
BinanceApiRestClient client = factory.newRestClient();
}
public List<com.herbron.moodl.DataManagers.CurrencyData.Trade> updateTrades(String symbol, String pairSymbol)
{
List<Trade> presentTrades = new ArrayList<>();
List<com.herbron.moodl.DataManagers.CurrencyData.Trade> customTrades = new ArrayList<>();
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(publicKey, privateKey);
BinanceApiRestClient client = factory.newRestClient();
if(!symbol.equals(pairSymbol))
{
try {
presentTrades = client.getMyTrades(symbol + pairSymbol);
} catch (BinanceApiException e) {
/*try {
presentTrades = client.getMyTrades(pairSymbol + symbol);
} catch (BinanceApiException f) {
f.printStackTrace();
}*/
}
}
for(int i = 0; i < presentTrades.size(); i++)
{
customTrades.add(new com.herbron.moodl.DataManagers.CurrencyData.Trade(symbol, pairSymbol, presentTrades.get(i)));
}
return customTrades;
}
public List<com.herbron.moodl.DataManagers.CurrencyData.Trade> updateTrades(String symbol, String pairSymbol, long fromId)
{
List<Trade> presentTrades = new ArrayList<>();
List<com.herbron.moodl.DataManagers.CurrencyData.Trade> customTrades = new ArrayList<>();
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(publicKey, privateKey);
BinanceApiRestClient client = factory.newRestClient();
if(!symbol.equals(pairSymbol))
{
try {
presentTrades = client.getMyTrades(symbol + pairSymbol, 20, fromId, System.currentTimeMillis(), System.currentTimeMillis());
} catch (BinanceApiException e) {
try {
presentTrades = client.getMyTrades(pairSymbol + symbol, 20, fromId, System.currentTimeMillis(), System.currentTimeMillis());
} catch (BinanceApiException f) {
f.printStackTrace();
}
}
}
for(int i = 0; i < presentTrades.size(); i++)
{
customTrades.add(new com.herbron.moodl.DataManagers.CurrencyData.Trade(symbol, pairSymbol, presentTrades.get(i)));
}
return customTrades;
}
public List<Currency> getBalance()
{
return balance;
}
public ArrayList<com.herbron.moodl.DataManagers.CurrencyData.Trade> getTrades()
{
return trades;
}
public interface BinanceCallBack {
void onSuccess();
void onError(String error);
}
}

View File

@ -0,0 +1,96 @@
package com.herbron.moodl.DataManagers.ExchangeManager;
import com.herbron.moodl.DataManagers.InfoAPIManagers.Pair;
import java.util.ArrayList;
import java.util.List;
public class Exchange {
protected int id;
protected String name;
protected int type;
protected String description;
protected String publicKey;
protected String privateKey;
protected boolean isEnabled;
private List<Pair> pairs;
public Exchange(int id, String name, int type, String description, String publicKey, String privateKey, boolean isEnabled)
{
this.id = id;
this.name = name;
this.type = type;
this.description = description;
this.publicKey = publicKey;
this.privateKey = privateKey;
this.isEnabled = isEnabled;
}
public Exchange(String name, List<Pair> pairs)
{
this.name = name;
this.pairs = pairs;
}
public Exchange(Exchange exchange)
{
this.name = exchange.name;
this.pairs = exchange.pairs;
}
public List<Pair> getPairs()
{
return pairs;
}
public boolean isEnabled()
{
return isEnabled;
}
public String getPublicKey()
{
return publicKey;
}
public String getPrivateKey()
{
return privateKey;
}
public int getType()
{
return type;
}
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
public int getId()
{
return id;
}
public List<Pair> getPairsFor(String symbol)
{
List<Pair> compatiblePairs = new ArrayList<>();
for(Pair pair : pairs)
{
if(pair.contains(symbol))
{
compatiblePairs.add(pair);
}
}
return compatiblePairs;
}
}

View File

@ -0,0 +1,259 @@
package com.herbron.moodl.DataManagers.ExchangeManager;
import android.util.Base64;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataNotifiers.HitBTCUpdateNotifierInterface;
import com.herbron.moodl.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Guitoune on 26/02/2018.
*/
public class HitBtcManager extends Exchange {
final private String hitBalanceUrl = "https://api.hitbtc.com/api/2/account/balance";
final private String hitTradingBalanceUrl = "https://api.hitbtc.com/api/2/trading/balance";
final private String tradeHistoryUrl = "https://api.hitbtc.com/api/2/history/trades?";
private RequestQueue requestQueue;
private List<String> pairSymbolList;
private boolean isTradingBalanceUpdated;
private boolean isBalanceUpdated;
private List<Currency> balance;
private android.content.Context context;
private List<HitBTCUpdateNotifierInterface> hitBTCUpdateNotifierInterfaceList;
public HitBtcManager(android.content.Context context, Exchange exchange)
{
super(exchange.id, exchange.name, exchange.type, exchange.description, exchange.publicKey, exchange.privateKey, exchange.isEnabled);
this.context = context;
requestQueue = Volley.newRequestQueue(context);
}
public void addListener(HitBTCUpdateNotifierInterface hitBTCUpdateNotifierInterface)
{
if(hitBTCUpdateNotifierInterfaceList == null)
{
hitBTCUpdateNotifierInterfaceList = new ArrayList<>();
}
hitBTCUpdateNotifierInterfaceList.add(hitBTCUpdateNotifierInterface);
}
private void createPairSymbolList()
{
pairSymbolList = new ArrayList<>();
pairSymbolList.add("BTC");
pairSymbolList.add("ETH");
pairSymbolList.add("BNB");
pairSymbolList.add("USDT");
}
private void mergeBalanceSymbols()
{
List<Currency> mergedBalance = new ArrayList<>();
for(int i = 0; i < balance.size(); i++)
{
boolean updated = false;
for(int j = 0; j < mergedBalance.size(); j++)
{
if(mergedBalance.get(j).getSymbol().equals(balance.get(i).getSymbol()))
{
mergedBalance.get(j).setBalance(mergedBalance.get(j).getBalance() + balance.get(i).getBalance());
updated = true;
}
}
if(!updated)
{
mergedBalance.add(balance.get(i));
}
}
balance = mergedBalance;
}
public void updateGlobalBalance()
{
isTradingBalanceUpdated = false;
isBalanceUpdated = false;
balance = new ArrayList<>();
updateBalance(new HitBtcCallBack() {
@Override
public void onSuccess() {
isBalanceUpdated = true;
if(isTradingBalanceUpdated)
{
mergeBalanceSymbols();
for(HitBTCUpdateNotifierInterface hitBTCUpdateNotifierInterface : hitBTCUpdateNotifierInterfaceList)
{
hitBTCUpdateNotifierInterface.onHitBTCBalanceUpdateSuccess();
}
}
}
@Override
public void onError(String error) {
for(HitBTCUpdateNotifierInterface hitBTCUpdateNotifierInterface : hitBTCUpdateNotifierInterfaceList)
{
hitBTCUpdateNotifierInterface.onHitBTCBalanceUpdateError(id, error);
}
}
});
updateTradingBalance(new HitBtcCallBack() {
@Override
public void onSuccess() {
isTradingBalanceUpdated = true;
if(isBalanceUpdated)
{
mergeBalanceSymbols();
for(HitBTCUpdateNotifierInterface hitBTCUpdateNotifierInterface : hitBTCUpdateNotifierInterfaceList)
{
hitBTCUpdateNotifierInterface.onHitBTCBalanceUpdateSuccess();
}
}
}
@Override
public void onError(String error) {
for(HitBTCUpdateNotifierInterface hitBTCUpdateNotifierInterface : hitBTCUpdateNotifierInterfaceList)
{
hitBTCUpdateNotifierInterface.onHitBTCBalanceUpdateError(id, error);
}
}
});
}
private void updateTradingBalance(final HitBtcCallBack callBack)
{
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.GET, hitTradingBalanceUrl
, getResponseListener(callBack), getErrorResponseListener(callBack))
{
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String credentials = publicKey + ":" + privateKey;
String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Content-Type", "application/json");
headers.put("Authorization", auth);
return headers;
}
};
requestQueue.add(arrayRequest);
}
private void updateBalance(final HitBtcCallBack callBack)
{
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.GET, hitBalanceUrl
, getResponseListener(callBack), getErrorResponseListener(callBack))
{
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String credentials = publicKey + ":" + privateKey;
String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Content-Type", "application/json");
headers.put("Authorization", auth);
return headers;
}
};
requestQueue.add(arrayRequest);
}
private Response.Listener<JSONArray> getResponseListener(final HitBtcCallBack callBack)
{
return new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
if (response.length() > 0) {
parseBalance(response);
}
callBack.onSuccess();
}
};
}
private Response.ErrorListener getErrorResponseListener(final HitBtcCallBack callBack)
{
return new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(context.getResources().getString(R.string.debug), "API Error : " + error);
callBack.onError(error.toString());
}
};
}
private void parseBalance(JSONArray response)
{
for(int i = 0; i < response.length(); i++)
{
try {
JSONObject jsonObject = response.getJSONObject(i);
double available = Double.parseDouble(jsonObject.getString("available"));
double reserved = Double.parseDouble(jsonObject.getString("reserved"));
if(available > 0 || reserved > 0)
{
switch (jsonObject.getString("currency"))
{
case "IOTA":
balance.add(new Currency("MIOTA", available + reserved));
break;
default:
balance.add(new Currency(jsonObject.getString("currency"), available + reserved));
break;
}
}
} catch (JSONException e) {
Log.e(context.getResources().getString(R.string.debug), "Invalid JSON Object");
}
}
}
public List<Currency> getBalance()
{
return balance;
}
public interface HitBtcCallBack {
void onSuccess();
void onError(String error);
}
}

View File

@ -0,0 +1,357 @@
package com.herbron.moodl.DataManagers.InfoAPIManagers;
import android.content.Context;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.herbron.moodl.DataNotifiers.CoinmarketcapNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Created by Guitoune on 22/04/2018.
*/
public class CoinmarketCapAPIManager {
final private static String LISTINGURL = "https://api.coinmarketcap.com/v2/listings/";
final private static String TICKERLISTURL1 = "https://api.coinmarketcap.com/v2/ticker/?start=";
private static final String topCurrenciesUrl = "https://api.coinmarketcap.com/v2/ticker/?limit=9&convert=";
private static final String marketCapUrl = "https://api.coinmarketcap.com/v2/global/?convert=";
private RequestQueue requestQueue;
private List<Currency> currencyTickerList;
private static CoinmarketCapAPIManager INSTANCE;
private boolean upToDate;
private List<Currency> topCurrencies;
private long marketCap;
private long dayVolume;
private String active_crypto;
private String active_markets;
private List<CoinmarketcapNotifierInterface> coinmarketcapNotifierInterfaceList;
private CoinmarketCapAPIManager(Context context)
{
requestQueue = Volley.newRequestQueue(context);
}
public static synchronized CoinmarketCapAPIManager getInstance(Context context)
{
if(INSTANCE == null)
{
INSTANCE = new CoinmarketCapAPIManager(context);
}
return INSTANCE;
}
public void addListener(CoinmarketcapNotifierInterface coinmarketcapNotifierInterface)
{
if(coinmarketcapNotifierInterfaceList == null)
{
coinmarketcapNotifierInterfaceList = new ArrayList<>();
}
coinmarketcapNotifierInterfaceList.add(coinmarketcapNotifierInterface);
}
public boolean isUpToDate()
{
if(currencyTickerList == null)
{
upToDate = false;
}
return upToDate;
}
public void getCurrenciesFrom(int indexFrom, final String toSymbol)
{
String requetsString = TICKERLISTURL1 + indexFrom + "&limit=50&convert=" + toSymbol;
StringRequest strRequest = new StringRequest(Request.Method.GET, requetsString,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0)
{
processTickersResult(response, toSymbol);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
public void updateListing()
{
currencyTickerList = new ArrayList<>();
StringRequest strRequest = new StringRequest(Request.Method.GET, LISTINGURL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processTickerListResult(response);
}
upToDate = true;
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
upToDate = true;
}
});
requestQueue.add(strRequest);
}
public int getTickerIdForSymbol(String symbol)
{
int tickerId = 0;
int i = 0;
while(!currencyTickerList.get(i).getSymbol().equals(symbol) && currencyTickerList.size() > i+1)
{
i++;
}
if(currencyTickerList.get(i).getSymbol().equals(symbol))
{
tickerId = currencyTickerList.get(i).getTickerId();
}
return tickerId;
}
private void processTickersResult(String response, String toSymbol)
{
List<Currency> currencyList = new ArrayList<>();
try {
JSONObject masterJsonObject = new JSONObject(response);
if(masterJsonObject.keys().hasNext())
{
JSONObject currencyJsonObject = masterJsonObject.getJSONObject(masterJsonObject.keys().next());
Iterator<?> keys = currencyJsonObject.keys();
while(keys.hasNext())
{
String key = keys.next().toString();
JSONObject subCurrencyJsonObject = currencyJsonObject.getJSONObject(key);
Currency newCurrency = new Currency(subCurrencyJsonObject.getString("name"), subCurrencyJsonObject.getString("symbol"), subCurrencyJsonObject.getInt("id"));
newCurrency.setRank(subCurrencyJsonObject.getInt("rank"));
JSONObject quoteJsonObject = subCurrencyJsonObject.getJSONObject("quotes");
JSONObject symJsonObject = quoteJsonObject.getJSONObject(toSymbol);
newCurrency.setValue(symJsonObject.getDouble("price"));
newCurrency.setDayFluctuationPercentage((float) symJsonObject.getDouble("percent_change_24h"));
newCurrency.setDayFluctuation(newCurrency.getDayFluctuationPercentage() * newCurrency.getValue() / 100);
currencyList.add(newCurrency);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
for(CoinmarketcapNotifierInterface coinmarketcapNotifierInterface : coinmarketcapNotifierInterfaceList)
{
coinmarketcapNotifierInterface.onCurrenciesRetrieved(currencyList);
}
}
private void processTickerListResult(String response)
{
try {
JSONObject dataJsonObject = new JSONObject(response);
JSONArray dataJsonArray = dataJsonObject.getJSONArray("data");
for(int i = 0; i < dataJsonArray.length(); i++)
{
JSONObject currencyJsonObject = dataJsonArray.getJSONObject(i);
currencyTickerList.add(new Currency(currencyJsonObject.getString("name"), currencyJsonObject.getString("symbol"), currencyJsonObject.getInt("id")));
}
} catch (JSONException e) {
e.printStackTrace();
}
for(CoinmarketcapNotifierInterface coinmarketcapNotifierInterface : coinmarketcapNotifierInterfaceList)
{
coinmarketcapNotifierInterface.onListingUpdated();
}
}
public List<Currency> getTotalListing()
{
return currencyTickerList;
}
public void updateTopCurrencies(final String toSymbol)
{
String requestString = topCurrenciesUrl + toSymbol;
topCurrencies = new ArrayList<>();
StringRequest strRequest = new StringRequest(Request.Method.GET, requestString,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processTopCurrencies(response, toSymbol);
}
for(CoinmarketcapNotifierInterface coinmarketcapNotifierInterface : coinmarketcapNotifierInterfaceList)
{
coinmarketcapNotifierInterface.onTopCurrenciesUpdated();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
public void updateMarketCap(final String toSymbol)
{
String requestString = marketCapUrl + toSymbol;
StringRequest strRequest = new StringRequest(Request.Method.GET, requestString,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processMarketCapData(response, toSymbol);
}
for(CoinmarketcapNotifierInterface coinmarketcapNotifierInterface : coinmarketcapNotifierInterfaceList)
{
coinmarketcapNotifierInterface.onMarketCapUpdated();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
private void processMarketCapData(String response, String toSymbol)
{
try {
JSONObject jsonObject = new JSONObject(response);
JSONObject dataJsonObject = jsonObject.getJSONObject("data");
JSONObject quotesJsonObject = dataJsonObject.getJSONObject("quotes");
JSONObject valuesJsonObject = quotesJsonObject.getJSONObject(toSymbol);
active_crypto = dataJsonObject.getString("active_cryptocurrencies");
active_markets = dataJsonObject.getString("active_markets");
marketCap = valuesJsonObject.getLong("total_market_cap");
dayVolume = valuesJsonObject.getLong("total_volume_24h");
} catch (JSONException e) {
e.printStackTrace();
}
}
public String getActive_crypto()
{
return active_crypto;
}
public String getActive_markets()
{
return active_markets;
}
public List<Currency> getTopCurrencies()
{
return topCurrencies;
}
public long getDayVolume()
{
return dayVolume;
}
private void processTopCurrencies(String response, String toSymbol)
{
try {
JSONObject masterJsonObject = new JSONObject(response);
if(masterJsonObject.keys().hasNext())
{
JSONObject currencyJsonObject = masterJsonObject.getJSONObject(masterJsonObject.keys().next());
Iterator<?> keys = currencyJsonObject.keys();
while(keys.hasNext())
{
String key = keys.next().toString();
JSONObject subCurrencyJsonObject = currencyJsonObject.getJSONObject(key);
Currency newCurrency = new Currency(subCurrencyJsonObject.getString("name"), subCurrencyJsonObject.getString("symbol"), subCurrencyJsonObject.getInt("id"));
JSONObject quoteJsonObject = subCurrencyJsonObject.getJSONObject("quotes");
JSONObject symJsonObject = quoteJsonObject.getJSONObject(toSymbol);
newCurrency.setMarketCapitalization(symJsonObject.getDouble("market_cap"));
newCurrency.setVolume24h(symJsonObject.getDouble("volume_24h"));
topCurrencies.add(newCurrency);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public Currency getCurrencyFromSymbol(String symbol)
{
Currency returnedCurrency = null;
int index = 0;
do {
if(symbol.equals(topCurrencies.get(index).getSymbol()))
{
returnedCurrency = topCurrencies.get(index);
}
index++;
} while(index < topCurrencies.size() && returnedCurrency == null);
return returnedCurrency;
}
public long getMarketCap()
{
return marketCap;
}
}

View File

@ -0,0 +1,313 @@
package com.herbron.moodl.DataManagers.InfoAPIManagers;
import android.content.Context;
import android.os.StrictMode;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.herbron.moodl.DataNotifiers.CryptocompareNotifierInterface;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.ExchangeManager.Exchange;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.regex.Pattern;
/**
* Created by Tiji on 11/04/2018.
*/
public class CryptocompareApiManager {
final private static String DETAILURL = "https://min-api.cryptocompare.com/data/all/coinlist";
final private static String EXCHANGEURL = "https://min-api.cryptocompare.com/data/all/exchanges";
private RequestQueue requestQueue;
private LinkedHashMap<String, String> coinInfosHashmap;
private List<Exchange> exchangeList;
private static CryptocompareApiManager INSTANCE;
private boolean exchangesUpToDate;
private boolean detailsUpToDate;
private List<CryptocompareNotifierInterface> cryptocompareNotifierInterfaceList;
private CryptocompareApiManager(Context context)
{
requestQueue = Volley.newRequestQueue(context);
}
public static synchronized CryptocompareApiManager getInstance(Context context)
{
if(INSTANCE == null)
{
INSTANCE = new CryptocompareApiManager(context);
}
return INSTANCE;
}
public void addListener(CryptocompareNotifierInterface cryptocompareNotifierInterface)
{
if(cryptocompareNotifierInterfaceList == null)
{
cryptocompareNotifierInterfaceList = new ArrayList<>();
}
cryptocompareNotifierInterfaceList.add(cryptocompareNotifierInterface);
}
public void updateExchangeList()
{
StringRequest stringRequest = new StringRequest(Request.Method.GET, EXCHANGEURL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
processExchangeResult(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(stringRequest);
}
public void updateDetails()
{
StringRequest strRequest = new StringRequest(Request.Method.GET, DETAILURL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processDetailResult(response);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
public boolean isExchangesUpToDate()
{
if(exchangeList == null)
{
exchangesUpToDate = false;
}
return exchangesUpToDate;
}
public boolean isDetailsUpToDate()
{
if(coinInfosHashmap == null)
{
detailsUpToDate = false;
}
return detailsUpToDate;
}
private void processExchangeResult(String response)
{
exchangeList = new ArrayList<>();
try {
JSONObject mainJsonObject = new JSONObject(response);
Iterator<String> exchangeIterator = mainJsonObject.keys();
while(exchangeIterator.hasNext())
{
String exchangeKey = exchangeIterator.next();
JSONObject exchangeJsonObject = mainJsonObject.getJSONObject(exchangeKey);
Iterator<String> pairIterator = exchangeJsonObject.keys();
List<Pair> pairList = new ArrayList<>();
while(pairIterator.hasNext())
{
String pairKey = pairIterator.next();
JSONArray pairJsonArray = exchangeJsonObject.getJSONArray(pairKey);
for(int i = 0; i < pairJsonArray.length(); i++)
{
pairList.add(new Pair(pairKey, pairJsonArray.get(i).toString()));
}
}
exchangeList.add(new Exchange(exchangeKey, pairList));
}
for(CryptocompareNotifierInterface cryptocompareNotifierInterface : cryptocompareNotifierInterfaceList)
{
cryptocompareNotifierInterface.onExchangesUpdated();
}
} catch (JSONException e) {
Log.d("moodl", "Error while processing exchange result");
}
}
public List<Exchange> getExchangeList(String symbol)
{
List<Exchange> compatibleExchanges = new ArrayList<>();
for(Exchange exchange : exchangeList)
{
int i = 0;
boolean isSymbolTraded = false;
while(i < exchange.getPairs().size() && !isSymbolTraded)
{
if(exchange.getPairs().get(i).contains(symbol))
{
compatibleExchanges.add(exchange);
isSymbolTraded = true;
}
i++;
}
}
return compatibleExchanges;
}
private void processDetailResult(String response)
{
response = response.substring(response.indexOf("\"Data\"") + 7, response.lastIndexOf("},\"BaseImageUrl\""));
String[] tab = response.split(Pattern.quote("},"));
coinInfosHashmap = new LinkedHashMap<>();
for(int i = 0; i < tab.length; i++)
{
tab[i] = tab[i].substring(tab[i].indexOf("\":{")+2, tab[i].length()) + "}";
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
JSONObject jsonObject = new JSONObject(tab[i]);
switch (jsonObject.getString("Symbol"))
{
case "IOT":
coinInfosHashmap.put("MIOTA", tab[i]);
break;
case "XRB":
coinInfosHashmap.put("NANO", tab[i]);
break;
default:
coinInfosHashmap.put(jsonObject.getString("Symbol"), tab[i]);
break;
}
} catch (JSONException e) {
Log.d("moodl", "ImageUrl not found.");
}
}
sortDetails();
detailsUpToDate = true;
for(CryptocompareNotifierInterface cryptocompareNotifierInterface : cryptocompareNotifierInterfaceList)
{
cryptocompareNotifierInterface.onDetailsUpdated();
}
}
private void sortDetails()
{
LinkedHashMap<String, String> sortedHashmap = new LinkedHashMap<>();
List<String> listInfos = new ArrayList<>(coinInfosHashmap.values());
List<String> listSymbols = new ArrayList<>(coinInfosHashmap.keySet());
for(int i = 0; i < coinInfosHashmap.keySet().size(); i++)
{
try {
JSONObject jsonObject = new JSONObject(listInfos.get(i));
int index = jsonObject.getInt("SortOrder");
listInfos.add(index, listInfos.get(i));
listSymbols.add(index, listSymbols.get(i));
} catch (JSONException e) {
e.printStackTrace();
}
}
for(int i = 0; i < listInfos.size(); i++)
{
sortedHashmap.put(listSymbols.get(i), listInfos.get(i));
}
coinInfosHashmap = sortedHashmap;
}
public LinkedHashMap<String, String> getCoinInfosHashmap() {
return coinInfosHashmap;
}
public List<String> getCurrenciesName()
{
List<String> currenciesName = new ArrayList<>();
for (String symbol : coinInfosHashmap.keySet())
{
try {
JSONObject jsonObject = new JSONObject(coinInfosHashmap.get(symbol));
currenciesName.add(jsonObject.getString("CoinName"));
} catch (JSONException e) {
e.printStackTrace();
}
}
return currenciesName;
}
public List<Currency> getCurrenciesDenomination()
{
List<Currency> currencies = new ArrayList<>();
for(String symbol : coinInfosHashmap.keySet())
{
try {
JSONObject jsonObject = new JSONObject(coinInfosHashmap.get(symbol));
currencies.add(new Currency(jsonObject.getString("CoinName"), symbol));
} catch (JSONException e) {
e.printStackTrace();
}
}
return currencies;
}
public Currency getCurrencyDetailsFromSymbol(String symbol)
{
//Currency currency = new Currency();
return null;
}
public List<String> getCurrenciesSymbol()
{
return new ArrayList<>(coinInfosHashmap.keySet());
}
}

View File

@ -0,0 +1,41 @@
package com.herbron.moodl.DataManagers.InfoAPIManagers;
public class Pair {
private String from;
private String to;
public Pair(String from, String to)
{
this.from = from;
this.to = to;
}
public Pair(Pair pair)
{
this.from = pair.from;
this.to = pair.to;
}
public boolean contains(String symbol)
{
symbol = symbol.toUpperCase();
return symbol.equals(from) || symbol.equals(to);
}
public String getFrom()
{
return from;
}
public String getTo()
{
return to;
}
@Override
public String toString() {
return from + "/" + to;
}
}

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio.DataManagers;
package com.herbron.moodl.DataManagers;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
@ -9,50 +9,28 @@ import android.preference.PreferenceManager;
public class PreferencesManager {
private static int fragmentUpdated = 0;
private static final String currencyListFile = "CustomCurrencies";
private static final String preferencesFile = "Preferences";
private SharedPreferences settingPreferences;
private SharedPreferences currencyList;
private SharedPreferences preferencesList;
public PreferencesManager(android.content.Context context)
{
settingPreferences = PreferenceManager.getDefaultSharedPreferences(context);
currencyList = context.getSharedPreferences(currencyListFile, 0);
preferencesList = context.getSharedPreferences(preferencesFile, 0);
}
public void setDetailOption(boolean isExtended)
public float getMinimumAmount()
{
SharedPreferences.Editor editor = preferencesList.edit();
editor.putBoolean("DetailOption", isExtended);
editor.apply();
}
String str = settingPreferences.getString("minimum_value_displayed", "0");
float ret;
public boolean getDetailOption()
{
return preferencesList.getBoolean("DetailOption", true);
}
public boolean mustRefreshDefaultCurrency()
{
fragmentUpdated++;
if(fragmentUpdated == 3)
if(str.equals(""))
{
disableRefreshDefaultCurrency();
fragmentUpdated = 0;
ret = 0;
}
else
{
ret = Float.valueOf(str);
}
return settingPreferences.getBoolean("refresh_default_currency", false);
}
private void disableRefreshDefaultCurrency()
{
SharedPreferences.Editor editor = settingPreferences.edit();
editor.putBoolean("refresh_default_currency", false);
editor.apply();
return ret;
}
public String getDefaultCurrency()
@ -60,19 +38,13 @@ public class PreferencesManager {
return settingPreferences.getString("default_currency", "USD");
}
public String getHitBTCPublicKey()
public boolean switchBalanceHiddenState()
{
return settingPreferences.getString("hitbtc_publickey", null);
}
SharedPreferences.Editor editor = settingPreferences.edit();
editor.putBoolean("hide_balance", !isBalanceHidden());
editor.apply();
public String getHitBTCPrivateKey()
{
return settingPreferences.getString("hitbtc_privatekey", null);
}
public boolean isHitBTCActivated()
{
return settingPreferences.getBoolean("enable_hitbtc", false);
return isBalanceHidden();
}
public boolean isBalanceHidden()
@ -87,16 +59,6 @@ public class PreferencesManager {
editor.apply();
}
public String getBinancePublicKey()
{
return settingPreferences.getString("binance_publickey", null);
}
public String getBinancePrivateKey()
{
return settingPreferences.getString("binance_privatekey", null);
}
public boolean isBinanceActivated()
{
return settingPreferences.getBoolean("enable_binance", false);

View File

@ -1,8 +1,8 @@
package com.nauk.coinfolio.DataManagers;
package com.herbron.moodl.DataManagers;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import java.util.List;

View File

@ -0,0 +1,12 @@
package com.herbron.moodl.DataNotifiers;
/**
* Created by Administrator on 17/06/2018.
*/
public interface BalanceUpdateNotifierInterface {
void onBalanceDataUpdated();
void onBalanceError(String error);
}

View File

@ -0,0 +1,14 @@
package com.herbron.moodl.DataNotifiers;
import com.herbron.moodl.DataManagers.CurrencyData.Trade;
import java.util.List;
public interface BinanceUpdateNotifierInterface {
void onBinanceTradesUpdated(List<Trade> trades);
void onBinanceBalanceUpdateSuccess();
void onBinanceBalanceUpdateError(int accountId, String error);
}

View File

@ -0,0 +1,16 @@
package com.herbron.moodl.DataNotifiers;
import com.herbron.moodl.DataManagers.CurrencyData.Currency;
import java.util.List;
public interface CoinmarketcapNotifierInterface {
void onCurrenciesRetrieved(List<Currency> currencyList);
void onTopCurrenciesUpdated();
void onMarketCapUpdated();
void onListingUpdated();
}

View File

@ -0,0 +1,9 @@
package com.herbron.moodl.DataNotifiers;
public interface CryptocompareNotifierInterface {
void onDetailsUpdated();
void onExchangesUpdated();
}

View File

@ -0,0 +1,9 @@
package com.herbron.moodl.DataNotifiers;
public interface HitBTCUpdateNotifierInterface {
void onHitBTCBalanceUpdateSuccess();
void onHitBTCBalanceUpdateError(int accountId, String error);
}

View File

@ -0,0 +1,9 @@
package com.herbron.moodl.DataNotifiers;
import android.graphics.Bitmap;
public interface MoodlboxNotifierInterface {
void onBitmapDownloaded(Bitmap bitmap);
}

View File

@ -0,0 +1,44 @@
package com.herbron.moodl;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import com.herbron.moodl.Activities.DetailsActivityFragments.ChartsFragment;
import com.herbron.moodl.Activities.DetailsActivityFragments.InformationFragment;
import com.herbron.moodl.Activities.DetailsActivityFragments.TransactionsFragment;
/**
* Created by Tiji on 13/05/2018.
*/
public class DetailsActivityPagerAdapter extends FragmentStatePagerAdapter {
private int numOfTabs;
public DetailsActivityPagerAdapter(FragmentManager fm, int numOfTabs)
{
super(fm);
this.numOfTabs = numOfTabs;
}
@Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
return new ChartsFragment();
case 1:
return new InformationFragment();
case 2:
return new TransactionsFragment();
default:
return null;
}
}
@Override
public int getCount() {
return numOfTabs;
}
}

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio.FingerprintToolkit;
package com.herbron.moodl.FingerprintToolkit;
import android.app.DialogFragment;
import android.graphics.PorterDuff;
@ -6,11 +6,10 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.mattprecious.swirl.SwirlView;
import com.nauk.coinfolio.R;
import com.herbron.moodl.R;
/**
* Created by Guitoune on 28/02/2018.
@ -36,7 +35,8 @@ public class FingerprintDialogFragment extends DialogFragment{
@Override
public void onClick(View view) {
dismiss();
getActivity().finish();
getActivity().getFragmentManager().popBackStack();
//getActivity().finish();
}
});
@ -56,10 +56,14 @@ public class FingerprintDialogFragment extends DialogFragment{
public void wrongFingerprint(String errorString)
{
((SwirlView) this.getView().findViewById(R.id.swirl)).clearColorFilter();
((SwirlView) this.getView().findViewById(R.id.swirlBackground)).clearColorFilter();
((SwirlView) this.getView().findViewById(R.id.swirl)).setState(SwirlView.State.ERROR);
((SwirlView) this.getView().findViewById(R.id.swirlBackground)).setState(SwirlView.State.ERROR);
SwirlView swirlView = this.getView().findViewById(R.id.swirl);
SwirlView swirlBackground = this.getView().findViewById(R.id.swirlBackground);
swirlView.clearColorFilter();
swirlView.setState(SwirlView.State.ERROR);
swirlBackground.clearColorFilter();
swirlBackground.setState(SwirlView.State.ERROR);
((TextView) this.getView().findViewById(R.id.fingerprint_error)).setText(errorString);
}

View File

@ -1,4 +1,4 @@
package com.nauk.coinfolio.FingerprintToolkit;
package com.herbron.moodl.FingerprintToolkit;
import android.Manifest;
import android.content.Context;
@ -8,6 +8,8 @@ import android.os.CancellationSignal;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import com.herbron.moodl.R;
/**
* Created by Guitoune on 28/02/2018.
*/
@ -39,7 +41,7 @@ public class FingerprintHandler extends FingerprintManager.AuthenticationCallbac
{
if(dialogFragment.isVisible())
{
dialogFragment.wrongFingerprint("Error");
dialogFragment.wrongFingerprint(context.getString(R.string.error));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@ -57,7 +59,7 @@ public class FingerprintHandler extends FingerprintManager.AuthenticationCallbac
{
if(dialogFragment.isVisible())
{
dialogFragment.wrongFingerprint("Wrong fingerprint");
dialogFragment.wrongFingerprint(context.getString(R.string.wrong_fingerprint));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {

View File

@ -0,0 +1,331 @@
package com.herbron.moodl;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import com.herbron.moodl.DataManagers.InfoAPIManagers.CryptocompareApiManager;
import com.herbron.moodl.DataNotifiers.MoodlboxNotifierInterface;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import static java.lang.Math.abs;
/**
* Created by Guitoune on 30/04/2018.
*/
public class MoodlBox {
public static void expandH(final View v) {
v.measure(CardView.LayoutParams.MATCH_PARENT, CardView.LayoutParams.WRAP_CONTENT);
int targetHeight = v.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = getHorizontalExpandAnimation(v);
// 1dp/ms
a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static Animation getHorizontalExpandAnimation(final View v)
{
final int targetHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? CardView.LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
return a;
}
public static void expandW(final View v, Animation a)
{
v.measure(CardView.LayoutParams.MATCH_PARENT, CardView.LayoutParams.WRAP_CONTENT);
int targetWidth = v.getMeasuredWidth();
v.getLayoutParams().width = 1;
v.setVisibility(View.VISIBLE);
a.setDuration((int)(targetWidth / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void expandW(final View v) {
expandW(v, getVerticalExpandAnimation(v));
}
public static Animation getVerticalExpandAnimation(final View v)
{
final int targetWidth = v.getMeasuredWidth();
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().width = interpolatedTime == 1
? CardView.LayoutParams.WRAP_CONTENT
: (int)(targetWidth * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
return a;
}
public static void collapseH(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapseW(final View v) {
final int initialWidth = v.getMeasuredWidth();
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1) {
v.setVisibility(View.GONE);
} else {
v.getLayoutParams().width = initialWidth - (int)(initialWidth * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int)(initialWidth / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static String numberConformer(double number)
{
String str;
if(abs(number) > 1)
{
str = String.format( Locale.UK, "%.2f", number).replaceAll("\\.?0*$", "");
}
else
{
str = String.format( Locale.UK, "%.4f", number).replaceAll("\\.?0*$", "");
}
if(!str.equals("Infinity"))
{
int counter = 0;
int i = str.indexOf(".");
if(i <= 0)
{
i = str.length();
}
for(i -= 1; i > 0; i--)
{
counter++;
if(counter == 3)
{
str = str.substring(0, i) + " " + str.substring(i, str.length());
counter = 0;
}
}
}
return str;
}
public static String getDateFromTimestamp(long timeStamp){
try{
SimpleDateFormat sdf = new SimpleDateFormat(" HH:mm dd/MM/yyyy", Locale.getDefault());
Date netDate = (new Date(timeStamp));
return sdf.format(netDate);
}
catch(Exception ex){
return "xx";
}
}
public static void getBitmapFromURL(String src, String symbol, Resources resources, Context context, MoodlboxNotifierInterface callBack)
{
Bitmap result;
if(src != null)
{
String size = src.substring(src.lastIndexOf("=") + 1, src.length());
String filepath = context.getCacheDir() + "/" + symbol + "x" + size + ".png";
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
result = BitmapFactory.decodeFile(filepath, options);
if(result == null)
{
try {
java.net.URL url = new java.net.URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
result = BitmapFactory.decodeStream(input);
FileOutputStream out = new FileOutputStream(filepath);
result.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (IOException e) {
Log.d("moodl", "Error while downloading " + symbol + " icon > " + e.getMessage());
Drawable defautlDrawable = resources.getDrawable(R.drawable.ic_panorama_fish_eye_24dp);
result = Bitmap.createBitmap(defautlDrawable.getIntrinsicWidth(), defautlDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
defautlDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
defautlDrawable.draw(canvas);
}
}
}
else
{
Log.d("moodl", "No URL for " + symbol);
Drawable defautlDrawable = resources.getDrawable(R.drawable.ic_panorama_fish_eye_24dp);
result = Bitmap.createBitmap(defautlDrawable.getIntrinsicWidth(), defautlDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
defautlDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
defautlDrawable.draw(canvas);
}
callBack.onBitmapDownloaded(result);
}
public static int getColor(int id, Context context)
{
int color;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
color = context.getColor(id);
}
else
{
color = context.getResources().getColor(id);
}
return color;
}
public static Drawable getDrawable(int id, Context context)
{
Drawable drawable;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
drawable = context.getDrawable(id);
}
else
{
drawable = context.getResources().getDrawable(id);
}
return drawable;
}
public static String getIconUrl(String symbol, CryptocompareApiManager cryptocompareApiManager)
{
return getIconUrl(symbol, 50, cryptocompareApiManager);
}
public static float convertDpToPx(float dp, Resources resources)
{
return dp * resources.getDisplayMetrics().density;
}
public static String getIconUrl(String symbol, int size, CryptocompareApiManager cryptocompareApiManager)
{
String url;
try {
JSONObject jsonObject = new JSONObject(cryptocompareApiManager.getCoinInfosHashmap().get(symbol));
url = "https://www.cryptocompare.com" + jsonObject.getString("ImageUrl") + "?width=" + size;
} catch (JSONException | NullPointerException e) {
url = null;
}
return url;
}
public static int getIconDominantColor(Context context, Bitmap icon)
{
if(icon != null)
{
Palette.Builder builder = Palette.from(icon);
return builder.generate().getDominantColor(getColor(R.color.default_color, context));
}
else
{
return getColor(R.color.default_color, context);
}
}
}

View File

@ -1,12 +1,18 @@
package com.nauk.coinfolio;
package com.herbron.moodl.Utils;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import android.content.Context;
import com.herbron.moodl.DataManagers.PreferencesManager;
import com.herbron.moodl.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Tiji on 19/04/2018.
*/
public class PlaceholderManager {
public class PlaceholderUtils {
public static String getValueString(String value, android.content.Context context)
{
@ -32,7 +38,37 @@ public class PlaceholderManager {
return formattedString;
}
public static String getValuePercentageString(String value, String percentage, android.content.Context context)
public static List<String> getFeeOptionsForSymbol(String symbol, Context context)
{
List<String> options = new ArrayList<>();
options.add(context.getResources().getString(R.string.fixedFee, symbol));
options.add(context.getResources().getString(R.string.percentageFee, symbol));
return options;
}
public static String getPairString(String pair1, String pair2, Context context)
{
return context.getResources().getString(R.string.pairPlaceholder, pair1, pair2);
}
public static String getDenomination(String coinName, String coinSymbol, Context context)
{
return context.getResources().getString(R.string.denomincationPlaceholder, coinName, coinSymbol);
}
public static String getEditTransactionString(String coinName, Context context)
{
return context.getResources().getString(R.string.edit_transaction, coinName);
}
public static String getEmitedPercentageString(String percentage, Context context)
{
return context.getResources().getString(R.string.emitedPlaceholder, percentage);
}
public static String getValuePercentageString(String value, String percentage, Context context)
{
PreferencesManager preferencesManager = new PreferencesManager(context);
String formattedString = null;
@ -147,4 +183,24 @@ public class PlaceholderManager {
{
return context.getResources().getString(R.string.timestampPlaceholder, date);
}
public static String getToString(String to, android.content.Context context)
{
return context.getResources().getString(R.string.toPlaceholder, to);
}
public static String getFromString(String from, android.content.Context context)
{
return context.getResources().getString(R.string.fromPlaceholder, from);
}
public static String getFromToString(String from, String to, android.content.Context context)
{
return context.getResources().getString(R.string.fromToPlaceholder, from, to);
}
public static String getToPairString(String from, String to, Context context)
{
return context.getResources().getString(R.string.toPairPlaceholder, from, to);
}
}

View File

@ -0,0 +1,42 @@
package com.herbron.moodl.Utils;
import android.content.Context;
import com.herbron.moodl.Activities.RecordTransactionFragments.TransferFragment;
import com.herbron.moodl.R;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class TransferUtils {
public static boolean isBalanceRelated(String str)
{
Set<String> set = new HashSet<>(Arrays.asList(TransferFragment.EXCHANGE_CODE, TransferFragment.WALLET_CODE));
return set.contains(str);
}
public static String getLabelFor(Context context, String str)
{
switch (str)
{
case "stra:e":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[0].toLowerCase();
case "stra:mw":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[1].toLowerCase();
case "stra:m":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[2].toLowerCase();
case "stra:smew":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[3].toLowerCase();
case "stra:a":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[4].toLowerCase();
case "stra:unk":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[5].toLowerCase();
case "stra:fo":
return context.getResources().getStringArray(R.array.from_transfer_options_string_array)[6].toLowerCase();
}
return null;
}
}

View File

@ -1,189 +0,0 @@
package com.nauk.coinfolio.Activities;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.ViewFlipper;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.formatter.PercentFormatter;
import com.nauk.coinfolio.DataManagers.BalanceManager;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyTickerList;
import com.nauk.coinfolio.DataManagers.MarketCapManager;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.LayoutManagers.HomeLayoutGenerator;
import com.nauk.coinfolio.PagerAdapter;
import com.nauk.coinfolio.R;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
//Use WilliamChart for charts https://github.com/diogobernardino/WilliamChart
//Auto refresh with predefined intervals
//Multiple portfolio (exchanges & custom)
//Add roadmap to buy a coin
//Add reddit link ?
//
public class HomeActivity extends AppCompatActivity {
private BottomNavigationView bottomNavigationView;
private ViewPager viewPager;
private BottomNavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
item.setChecked(true);
switch (item.getItemId())
{
case R.id.navigation_watchlist:
viewPager.setCurrentItem(0);
break;
case R.id.navigation_currencies_list:
viewPager.setCurrentItem(1);
break;
case R.id.navigation_market_cap:
viewPager.setCurrentItem(2);
break;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**Interface setup**/
//Setup main interface
//requestWindowFeature(Window.FEATURE_NO_TITLE);
//getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
//this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
setContentView(R.layout.activity_currency_summary);
viewPager = findViewById(R.id.viewPager);
final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), 3);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(!bottomNavigationView.getMenu().getItem(position).isChecked())
{
bottomNavigationView.getMenu().getItem(position).setChecked(true);
}
if(position % 2 == 0)
{
((AppBarLayout) findViewById(R.id.app_bar)).setExpanded(false, true);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
//Objects initialization
//Layouts setup
bottomNavigationView = findViewById(R.id.navigationSummary);
bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener);
bottomNavigationView.setSelectedItemId(R.id.navigation_currencies_list);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.menu_currency_summary, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id)
{
/*case R.id.action_settings:
Log.d(this.getResources().getString(R.string.debug), "Setting button toggled");
break;*/
}
return super.onOptionsItemSelected(item);
}
public interface IconCallBack
{
void onSuccess(Bitmap bitmap);
}
}

View File

@ -1,301 +0,0 @@
package com.nauk.coinfolio.Activities.HomeActivityFragments;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import android.support.design.widget.AppBarLayout;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.SpannableString;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageButton;
import android.widget.TextView;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.formatter.PercentFormatter;
import com.nauk.coinfolio.Activities.SettingsActivity;
import com.nauk.coinfolio.DataManagers.MarketCapManager;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.PlaceholderManager;
import com.nauk.coinfolio.R;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import static java.lang.Math.abs;
/**
* Created by Tiji on 13/04/2018.
*/
public class MarketCapitalization extends Fragment {
private int marketCapCounter;
private PreferencesManager preferencesManager;
private MarketCapManager marketCapManager;
private HashMap<String, Integer> dominantCurrenciesColors;
private SwipeRefreshLayout refreshLayout;
private long lastTimestamp;
private String defaultCurrency;
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
preferencesManager = new PreferencesManager(getContext());
view = inflater.inflate(R.layout.fragment_marketcap_homeactivity, container, false);
setupDominantCurrenciesColors();
marketCapManager = new MarketCapManager(getContext());
refreshLayout = view.findViewById(R.id.swiperefreshmarketcap);
refreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateMarketCap(false);
}
}
);
defaultCurrency = preferencesManager.getDefaultCurrency();
lastTimestamp = 0;
ImageButton settingsButton = view.findViewById(R.id.settings_button);
settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent settingIntent = new Intent(getActivity(), SettingsActivity.class);
startActivity(settingIntent);
}
});
updateMarketCap(true);
return view;
}
@Override
public void onResume()
{
super.onResume();
if(!defaultCurrency.equals(preferencesManager.getDefaultCurrency()))
{
defaultCurrency = preferencesManager.getDefaultCurrency();
updateMarketCap(true);
}
else
{
updateMarketCap(false);
}
}
private void setupDominantCurrenciesColors()
{
dominantCurrenciesColors = new HashMap<>();
dominantCurrenciesColors.put("BTC", -489456);
dominantCurrenciesColors.put("ETH", -13619152);
dominantCurrenciesColors.put("XRP", -16744256);
dominantCurrenciesColors.put("BCH", -1011696);
dominantCurrenciesColors.put("LTC", -4671304);
dominantCurrenciesColors.put("EOS", -1513240);
dominantCurrenciesColors.put("ADA", -16773080);
dominantCurrenciesColors.put("XLM", -11509656);
dominantCurrenciesColors.put("MIOTA", -1513240);
dominantCurrenciesColors.put("NEO", -9390048);
dominantCurrenciesColors.put("XMR", -499712);
dominantCurrenciesColors.put("DASH", -15175496);
dominantCurrenciesColors.put("XEM", -7829368);
dominantCurrenciesColors.put("TRX", -7829360);
dominantCurrenciesColors.put("ETC", -10448784);
}
private void updateMarketCap(boolean mustUpdate)
{
if(System.currentTimeMillis() / 1000 - lastTimestamp > 60 || mustUpdate)
{
if(!refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(true);
}
marketCapCounter = 0;
lastTimestamp = System.currentTimeMillis() / 1000;
marketCapManager.updateTopCurrencies(new MarketCapManager.VolleyCallBack() {
@Override
public void onSuccess()
{
countCompletedMarketCapRequest();
}
}, preferencesManager.getDefaultCurrency());
marketCapManager.updateMarketCap(new MarketCapManager.VolleyCallBack() {
@Override
public void onSuccess() {
countCompletedMarketCapRequest();
}
}, preferencesManager.getDefaultCurrency());
}
else
{
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
}
private void refreshDisplayedData()
{
setupTextViewMarketCap();
view.findViewById(R.id.progressBarMarketCap).setVisibility(View.GONE);
view.findViewById(R.id.layoutProgressMarketCap).setVisibility(View.VISIBLE);
List<PieEntry> entries = new ArrayList<>();
ArrayList<Integer> colors = new ArrayList<>();
float otherCurrenciesDominance = 0;
for (String key : marketCapManager.getDominance(preferencesManager.getDefaultCurrency()).keySet())
{
entries.add(new PieEntry(marketCapManager.getDominance(preferencesManager.getDefaultCurrency()).get(key), key));
otherCurrenciesDominance += marketCapManager.getDominance(preferencesManager.getDefaultCurrency()).get(key);
colors.add(dominantCurrenciesColors.get(key));
}
entries.add(new PieEntry(100-otherCurrenciesDominance, "Others"));
colors.add(-12369084);
PieDataSet set = new PieDataSet(entries, "Market Cap Dominance");
set.setColors(colors);
set.setSliceSpace(1);
set.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
set.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
PieData data = new PieData(set);
data.setValueTextSize(10);
data.setValueFormatter(new PercentFormatter());
setupPieChart(data);
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
@SuppressLint("ClickableViewAccessibility")
private void countCompletedMarketCapRequest()
{
marketCapCounter++;
if(marketCapCounter == 2)
{
refreshDisplayedData();
}
}
private void setupPieChart(PieData data)
{
PieChart pieChart = view.findViewById(R.id.marketCapPieChart);
pieChart.setData(data);
pieChart.setDrawSlicesUnderHole(false);
pieChart.setUsePercentValues(true);
pieChart.setTouchEnabled(true);
pieChart.setEntryLabelColor(Color.parseColor("#FF000000"));
pieChart.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
refreshLayout.setEnabled(false);
break;
case MotionEvent.ACTION_MOVE:
break;
default:
refreshLayout.setEnabled(true);
break;
}
return false;
}
});
pieChart.getDescription().setEnabled(false);
pieChart.getLegend().setEnabled(false);
pieChart.setCenterText(generateCenterSpannableText());
pieChart.invalidate();
}
private String numberConformer(double number)
{
String str;
if(abs(number) > 1)
{
str = String.format( Locale.UK, "%.2f", number).replaceAll("\\.?0*$", "");
}
else
{
str = String.format( Locale.UK, "%.4f", number).replaceAll("\\.?0*$", "");
}
int counter = 0;
for(int i = str.length() - 1; i > 0; i--)
{
counter++;
if(counter == 3)
{
str = str.substring(0, i) + " " + str.substring(i, str.length());
counter = 0;
}
}
return str;
}
private SpannableString generateCenterSpannableText() {
SpannableString spannableString = new SpannableString("Market Capitalization Dominance");
return spannableString;
}
private void setupTextViewMarketCap()
{
((TextView) view.findViewById(R.id.marketCapTextView))
.setText(PlaceholderManager.getValueString(numberConformer(marketCapManager.getMarketCap()), getActivity()));
((TextView) view.findViewById(R.id.dayVolumeTotalMarketCap))
.setText(PlaceholderManager.getValueString(numberConformer(marketCapManager.getDayVolume()), getActivity()));
}
}

View File

@ -1,731 +0,0 @@
package com.nauk.coinfolio.Activities.HomeActivityFragments;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.graphics.Palette;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.nauk.coinfolio.Activities.CurrencySelectionActivity;
import com.nauk.coinfolio.Activities.HomeActivity;
import com.nauk.coinfolio.Activities.SettingsActivity;
import com.nauk.coinfolio.DataManagers.BalanceManager;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyTickerList;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.LayoutManagers.HomeLayoutGenerator;
import com.nauk.coinfolio.PlaceholderManager;
import com.nauk.coinfolio.R;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import static java.lang.Math.abs;
/**
* Created by Tiji on 13/04/2018.
*/
public class Summary extends Fragment {
private LinearLayout currencyLayout;
private PreferencesManager preferencesManager;
private BalanceManager balanceManager;
private HomeLayoutGenerator layoutGenerator;
private SwipeRefreshLayout refreshLayout;
private Dialog loadingDialog;
private String defaultCurrency;
private CurrencyTickerList currencyTickerList;
private TextView toolbarSubtitle;
private CollapsingToolbarLayout toolbarLayout;
private Handler handler;
private Runnable updateRunnable;
private int coinCounter;
private int iconCounter;
private float totalValue;
private boolean detailsChecker;
private boolean tickersChecker;
protected float totalFluctuation;
private long lastTimestamp;
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View fragmentView = inflater.inflate(R.layout.fragment_summary_homeactivity, container, false);
currencyLayout = fragmentView.findViewById(R.id.currencyListLayout);
preferencesManager = new PreferencesManager(getActivity());
balanceManager = new BalanceManager(getActivity());
layoutGenerator = new HomeLayoutGenerator(getActivity());
refreshLayout = fragmentView.findViewById(R.id.swiperefreshsummary);
toolbarSubtitle = fragmentView.findViewById(R.id.toolbarSubtitle);
currencyTickerList = new CurrencyTickerList(getActivity());
totalValue = 0;
totalFluctuation = 0;
lastTimestamp = 0;
tickersChecker = false;
defaultCurrency = preferencesManager.getDefaultCurrency();
handler = new Handler();
updateRunnable = new Runnable() {
@Override
public void run() {
if (refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
showErrorSnackbar();
}
if (loadingDialog.isShowing())
{
loadingDialog.dismiss();
showErrorSnackbar();
}
}
};
refreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateAll(false);
}
}
);
handler.postDelayed(updateRunnable, 10000);
toolbarLayout = fragmentView.findViewById(R.id.toolbar_layout);
toolbarLayout.setForegroundGravity(Gravity.CENTER);
Button addCurrencyButton = fragmentView.findViewById(R.id.buttonAddTransaction);
ImageButton settingsButton = fragmentView.findViewById(R.id.settings_button);
settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent settingIntent = new Intent(getActivity(), SettingsActivity.class);
startActivity(settingIntent);
}
});
addCurrencyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent addIntent = new Intent(getActivity(), CurrencySelectionActivity.class);
startActivity(addIntent);
}
});
updateAll(true);
generateSplashScreen();
return fragmentView;
}
private void generateSplashScreen()
{
LinearLayout loadingLayout = new LinearLayout(getActivity());
loadingLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
loadingLayout.setGravity(Gravity.CENTER);
loadingLayout.setOrientation(LinearLayout.VERTICAL);
loadingDialog = new Dialog(getActivity(), android.R.style.Theme_Black_NoTitleBar_Fullscreen);
TextView txtView = new TextView(getActivity());
txtView.setText("Loading data...");
txtView.setTextSize(20);
txtView.setGravity(Gravity.CENTER);
txtView.setTextColor(this.getResources().getColor(R.color.cardview_light_background));
ProgressBar progressBar = new ProgressBar(getActivity());
progressBar.setIndeterminate(true);
loadingLayout.setBackgroundColor(getActivity().getResources().getColor(R.color.colorPrimaryDark));
loadingLayout.addView(txtView);
loadingLayout.addView(progressBar);
loadingDialog.setContentView(loadingLayout);
loadingDialog.show();
}
@Override
public void onResume() {
super.onResume();
displayBalance(preferencesManager.isBalanceHidden());
if(!defaultCurrency.equals(preferencesManager.getDefaultCurrency()))
{
defaultCurrency = preferencesManager.getDefaultCurrency();
updateAll(true);
}
else
{
updateAll(preferencesManager.mustUpdateSummary());
}
}
private void updateAll(boolean mustUpdate)
{
if(System.currentTimeMillis()/1000 - lastTimestamp > 60 || mustUpdate)
{
if(!refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(true);
}
lastTimestamp = System.currentTimeMillis() / 1000;
balanceManager.updateExchangeKeys();
refreshLayout.setRefreshing(true);
resetCounters();
DataUpdater updater = new DataUpdater();
updater.execute();
}
else
{
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
}
private void showErrorSnackbar()
{
/*Snackbar.make(getActivity().findViewById(R.id.viewFlipperSummary), "Error while updating data", Snackbar.LENGTH_LONG)
.setAction("Update", new View.OnClickListener() {
@Override
public void onClick(View view) {
}
})
.show();*/
}
private void resetCounters()
{
coinCounter = 0;
iconCounter = 0;
detailsChecker = false;
totalValue = 0;
totalFluctuation = 0;
}
private void adaptView()
{
currencyLayout.removeAllViews();
final List<View> currencyView = new ArrayList<>();
Runnable newRunnable = new Runnable() {
@Override
public void run() {
if (balanceManager.getTotalBalance() != null)
{
for (int i = 0; i < balanceManager.getTotalBalance().size(); i++) {
final Currency currency = balanceManager.getTotalBalance().get(i);
if (!currency.getSymbol().equals("USD") && ((currency.getBalance() * currency.getValue()) > 0.001)) {
currencyView.add(layoutGenerator.getInfoLayout(currency, totalValue, preferencesManager.isBalanceHidden()));
}
}
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < currencyView.size(); i++)
{
currencyLayout.addView(currencyView.get(i));
}
if(loadingDialog.isShowing())
{
loadingDialog.dismiss();
}
}
});
}
};
newRunnable.run();
}
private void countCoins(boolean isCoin, boolean isDetails, boolean isTickers)
{
if(isCoin)
{
coinCounter++;
}
if(isTickers)
{
tickersChecker = true;
}
if(isDetails)
{
detailsChecker = true;
}
if(balanceManager.getTotalBalance() != null)
{
if(coinCounter == balanceManager.getTotalBalance().size() && detailsChecker && tickersChecker)
{
IconDownloader iconDownloader = new IconDownloader();
iconDownloader.execute();
}
else
{
if(balanceManager.getTotalBalance().size() == 0)
{
countIcons();
}
}
}
}
private void countIcons()
{
int offset = 0;
for(int i = 0; i < balanceManager.getTotalBalance().size(); i++)
{
if(balanceManager.getTotalBalance().get(i).getSymbol().equals("USD"))
{
offset++;
}
}
iconCounter++;
if(balanceManager.getTotalBalance() != null)
{
if(balanceManager.getTotalBalance().size() == 0)
{
updateNoBalance();
}
else
{
if(iconCounter == balanceManager.getTotalBalance().size() - offset)
{
Log.d(getResources().getString(R.string.debug), "Loading heavy");
UiHeavyLoadCalculator uiHeavyLoadCalculator = new UiHeavyLoadCalculator();
uiHeavyLoadCalculator.execute();
}
}
}
}
private void updateNoBalance()
{
refreshLayout.setRefreshing(false);
currencyLayout.removeAllViews();
if(loadingDialog.isShowing())
{
loadingDialog.dismiss();
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateTitle();
}
});
}
protected void updateTitle()
{
float totalFluctuationPercentage = totalFluctuation / (totalValue - totalFluctuation) * 100;
if(preferencesManager.isBalanceHidden())
{
toolbarLayout.setTitle(PlaceholderManager.getPercentageString(numberConformer(totalFluctuationPercentage), getActivity()));
toolbarSubtitle.setVisibility(View.GONE);
if(totalFluctuation > 0)
{
toolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.increase));
toolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.increase));
}
else
{
toolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.decrease));
toolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.decrease));
}
}
else
{
toolbarLayout.setTitle(PlaceholderManager.getValueString(numberConformer(totalValue), getActivity()));
toolbarLayout.setCollapsedTitleTextColor(Color.WHITE);
toolbarLayout.setExpandedTitleColor(Color.WHITE);
toolbarSubtitle.setVisibility(View.VISIBLE);
if(totalFluctuation > 0)
{
toolbarSubtitle.setTextColor(getResources().getColor(R.color.increase));
}
else
{
toolbarSubtitle.setTextColor(getResources().getColor(R.color.decrease));
}
if(totalFluctuation == 0)
{
toolbarSubtitle.setText(PlaceholderManager.getValueString(numberConformer(totalValue), getActivity()));
toolbarSubtitle.setTextColor(-1275068417);
}
else
{
toolbarSubtitle.setText(PlaceholderManager.getValuePercentageString(numberConformer(totalFluctuation), numberConformer(totalFluctuationPercentage), getActivity()));
}
}
}
private String numberConformer(double number)
{
String str;
if(abs(number) > 1)
{
str = String.format( Locale.UK, "%.2f", number).replaceAll("\\.?0*$", "");
}
else
{
str = String.format( Locale.UK, "%.4f", number).replaceAll("\\.?0*$", "");
}
int counter = 0;
int i = str.indexOf(".");
if(i <= 0)
{
i = str.length();
}
for(i -= 1; i > 0; i--)
{
counter++;
if(counter == 3)
{
str = str.substring(0, i) + " " + str.substring(i, str.length());
counter = 0;
}
}
return str;
}
private class UiHeavyLoadCalculator extends AsyncTask<Void, Integer, Void>
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
totalValue = 0;
totalFluctuation = 0;
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
}
private void updateChartColor(Currency currency)
{
if(currency.getIcon() != null)
{
Palette.Builder builder = Palette.from(currency.getIcon());
currency.setChartColor(builder.generate().getDominantColor(0));
}
else
{
currency.setChartColor(12369084);
}
}
private void loadCurrency(Currency currency)
{
if(!currency.getSymbol().equals("USD") && (currency.getBalance() * currency.getValue()) > 0.001)
{
currency.setName(balanceManager.getCurrencyName(currency.getSymbol()));
currency.setId(balanceManager.getCurrencyId(currency.getSymbol()));
totalValue += currency.getValue() * currency.getBalance();
totalFluctuation += (currency.getValue() * currency.getBalance()) * (currency.getDayFluctuationPercentage() / 100);
}
}
@Override
protected Void doInBackground(Void... params)
{
if(Looper.myLooper() == null)
{
Looper.prepare();
}
balanceManager.sortCoins();
for(int i = 0; i < balanceManager.getTotalBalance().size(); i++)
{
final Currency localCurrency = balanceManager.getTotalBalance().get(i);
localCurrency.setTickerId(currencyTickerList.getTickerIdForSymbol(localCurrency.getSymbol()));
updateChartColor(localCurrency);
loadCurrency(localCurrency);
balanceManager.getTotalBalance().set(i, localCurrency);
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateTitle();
}
});
return null;
}
@Override
protected void onPostExecute(Void result)
{
refreshLayout.setRefreshing(false);
//refreshCurrencyList();
adaptView();
handler.removeCallbacks(updateRunnable);
}
}
private void getBitmapFromURL(String src, HomeActivity.IconCallBack callBack) {
Bitmap result;
try {
java.net.URL url = new java.net.URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
result = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
result = BitmapFactory.decodeResource(this.getResources(),
R.mipmap.icon_coinfolio);
result = Bitmap.createScaledBitmap(result, 50, 50, false);
}
callBack.onSuccess(result);
}
private void displayBalance(boolean hideBalance)
{
updateTitle();
if(hideBalance)
{
for(int i = 0; i < currencyLayout.getChildCount(); i++)
{
currencyLayout.getChildAt(i).findViewById(R.id.currencyPortfolioDominance).setVisibility(View.VISIBLE);
currencyLayout.getChildAt(i).findViewById(R.id.percentageOwnedTextView).setVisibility(View.VISIBLE);
currencyLayout.getChildAt(i).findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.GONE);
}
}
else
{
for(int i = 0; i < currencyLayout.getChildCount(); i++)
{
currencyLayout.getChildAt(i).findViewById(R.id.currencyPortfolioDominance).setVisibility(View.INVISIBLE);
currencyLayout.getChildAt(i).findViewById(R.id.percentageOwnedTextView).setVisibility(View.GONE);
currencyLayout.getChildAt(i).findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.VISIBLE);
}
}
}
private class IconDownloader extends AsyncTask<Void, Integer, Void>
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
}
@Override
protected Void doInBackground(Void... params)
{
for (int i = 0; i < balanceManager.getTotalBalance().size(); i++)
{
final Currency localCurrency = balanceManager.getTotalBalance().get(i);
if(balanceManager.getIconUrl(localCurrency.getSymbol()) != null)
{
getBitmapFromURL(balanceManager.getIconUrl(localCurrency.getSymbol()), new HomeActivity.IconCallBack() {
@Override
public void onSuccess(Bitmap bitmapIcon) {
localCurrency.setIcon(bitmapIcon);
countIcons();
}
});
}
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
}
}
private class DataUpdater extends AsyncTask<Void, Integer, Void>
{
@Override
protected Void doInBackground(Void... params)
{
currencyTickerList.update(new BalanceManager.IconCallBack() {
@Override
public void onSuccess() {
countCoins(false, false, true);
}
});
balanceManager.updateDetails(new BalanceManager.IconCallBack() {
@Override
public void onSuccess()
{
countCoins(false, true, false);
}
});
balanceManager.updateTotalBalance(new BalanceManager.VolleyCallBack() {
@Override
public void onSuccess() {
final List<Currency> balance = balanceManager.getTotalBalance();
if(balanceManager.getTotalBalance().size() > 0)
{
for(int i = 0; i < balanceManager.getTotalBalance().size(); i++)
{
balance.get(i).updatePrice(getActivity(), defaultCurrency, new Currency.CurrencyCallBack() {
@Override
public void onSuccess(Currency currency) {
countCoins(true, false, false);
}
});
}
}
else
{
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
countCoins(false, false, false);
}
});
}
}
public void onError(String error)
{
View view = getActivity().findViewById(R.id.snackbar_placer);
switch (error)
{
case "com.android.volley.AuthFailureError":
preferencesManager.disableHitBTC();
Snackbar.make(view, "HitBTC synchronization error : Invalid keys", Snackbar.LENGTH_LONG)
.show();
refreshLayout.setRefreshing(false);
updateAll(true);
break;
case "API-key format invalid.":
preferencesManager.disableBinance();
Snackbar.make(view, "Binance synchronization error : Invalid keys", Snackbar.LENGTH_LONG)
.show();
updateAll(true);
break;
default:
Snackbar.make(view, "Unexpected error", Snackbar.LENGTH_LONG)
.show();
Log.d("coinfolio", error);
updateAll(true);
}
}
});
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
}

View File

@ -1,684 +0,0 @@
package com.nauk.coinfolio.Activities.HomeActivityFragments;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.CardView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.nauk.coinfolio.Activities.CurrencyDetailsActivity;
import com.nauk.coinfolio.Activities.CurrencySelectionActivity;
import com.nauk.coinfolio.Activities.HomeActivity;
import com.nauk.coinfolio.Activities.SettingsActivity;
import com.nauk.coinfolio.DataManagers.BalanceManager;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyDataChart;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyDetailsList;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyTickerList;
import com.nauk.coinfolio.DataManagers.DatabaseManager;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.DataManagers.WatchlistManager;
import com.nauk.coinfolio.PlaceholderManager;
import com.nauk.coinfolio.R;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import static java.lang.Math.abs;
/**
* Created by Tiji on 13/04/2018.
*/
public class Watchlist extends Fragment {
private WatchlistManager watchlistManager;
private View view;
private int watchlistCounter;
private CurrencyDetailsList currencyDetailsList;
private SwipeRefreshLayout refreshLayout;
private long lastTimestamp;
private PreferencesManager preferencesManager;
private String defaultCurrency;
private CurrencyTickerList currencyTickerList;
private boolean tickerUpdated;
private boolean detailsUpdated;
private boolean editModeEnabled;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.fragment_watchlist_homeactivity, container, false);
refreshLayout = view.findViewById(R.id.swiperefreshwatchlist);
currencyDetailsList = new CurrencyDetailsList(getContext());
preferencesManager = new PreferencesManager(getContext());
lastTimestamp = 0;
defaultCurrency = preferencesManager.getDefaultCurrency();
currencyTickerList = new CurrencyTickerList(getActivity());
tickerUpdated = false;
currencyTickerList.update(new BalanceManager.IconCallBack() {
@Override
public void onSuccess() {
tickerUpdated = true;
checkUpdatedData();
}
});
editModeEnabled = false;
watchlistManager = new WatchlistManager(getContext());
updateWatchlist(true);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateWatchlist(false);
}
});
Button addWatchlistButton = view.findViewById(R.id.buttonAddWatchlist);
addWatchlistButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent selectionIntent = new Intent(getActivity(), CurrencySelectionActivity.class);
selectionIntent.putExtra("isWatchList", true);
startActivity(selectionIntent);
}
});
ImageButton settingsButton = view.findViewById(R.id.settings_button);
settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent settingIntent = new Intent(getActivity(), SettingsActivity.class);
startActivity(settingIntent);
}
});
ImageButton editButton = view.findViewById(R.id.edit_button);
editButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(editModeEnabled)
{
editModeEnabled = false;
for(int i = 0; i < ((LinearLayout) Watchlist.this.view.findViewById(R.id.linearLayoutWatchlist)).getChildCount(); i++)
{
((LinearLayout) Watchlist.this.view.findViewById(R.id.linearLayoutWatchlist)).getChildAt(i).setClickable(true);
collapseW(((LinearLayout) Watchlist.this.view.findViewById(R.id.linearLayoutWatchlist)).getChildAt(i).findViewById(R.id.deleteCardWatchlist));
}
}
else
{
editModeEnabled = true;
for(int i = 0; i < ((LinearLayout) Watchlist.this.view.findViewById(R.id.linearLayoutWatchlist)).getChildCount(); i++)
{
((LinearLayout) Watchlist.this.view.findViewById(R.id.linearLayoutWatchlist)).getChildAt(i).setClickable(false);
expandW(((LinearLayout) Watchlist.this.view.findViewById(R.id.linearLayoutWatchlist)).getChildAt(i).findViewById(R.id.deleteCardWatchlist));
}
}
}
});
return view;
}
private void collapseView(View view)
{
collapse(view.findViewById(R.id.collapsableLayout));
}
private void extendView(View view)
{
expand(view.findViewById(R.id.collapsableLayout));
view.findViewById(R.id.LineChartView).invalidate();
}
private static void expand(final View v) {
v.measure(CardView.LayoutParams.MATCH_PARENT, CardView.LayoutParams.WRAP_CONTENT);
final int targetHeight = v.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? CardView.LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
private static void expandW(final View v) {
v.measure(CardView.LayoutParams.MATCH_PARENT, CardView.LayoutParams.WRAP_CONTENT);
final int targetWidth = v.getMeasuredWidth();
v.getLayoutParams().width = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().width = interpolatedTime == 1
? CardView.LayoutParams.WRAP_CONTENT
: (int)(targetWidth * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int)(targetWidth / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
private static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
private static void collapseW(final View v) {
final int initialWidth = v.getMeasuredWidth();
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1) {
v.setVisibility(View.GONE);
} else {
v.getLayoutParams().width = initialWidth - (int)(initialWidth * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int)(initialWidth / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
@Override
public void onResume()
{
super.onResume();
if(!defaultCurrency.equals(preferencesManager.getDefaultCurrency()))
{
defaultCurrency = preferencesManager.getDefaultCurrency();
updateWatchlist(true);
}
else
{
updateWatchlist(preferencesManager.mustUpdateWatchlist());
}
}
private void updateWatchlist(boolean mustUpdate)
{
if(System.currentTimeMillis()/1000 - lastTimestamp > 60 || mustUpdate)
{
if(!refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(true);
}
lastTimestamp = System.currentTimeMillis()/1000;
detailsUpdated = false;
watchlistManager.updateWatchlist();
currencyDetailsList.update(new BalanceManager.IconCallBack() {
@Override
public void onSuccess() {
detailsUpdated = true;
checkUpdatedData();
}
});
}
else
{
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
}
private void checkUpdatedData()
{
if(tickerUpdated && detailsUpdated)
{
WatchlistUpdater watchlistUpdater = new WatchlistUpdater();
watchlistUpdater.execute();
}
}
private void generateCards()
{
final List<View> watchlistViews = new ArrayList<View>();
((LinearLayout) view.findViewById(R.id.linearLayoutWatchlist)).removeAllViews();
Runnable newRunnable = new Runnable() {
@Override
public void run() {
for(final Currency currency : watchlistManager.getWatchlist())
{
watchlistViews.add(getCurrencyCardFor(currency));
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < watchlistViews.size(); i++)
{
((LinearLayout) view.findViewById(R.id.linearLayoutWatchlist)).addView(watchlistViews.get(i), 0);
}
}
});
}
};
newRunnable.run();
if(refreshLayout.isRefreshing())
{
refreshLayout.setRefreshing(false);
}
}
private void countWatchlist()
{
watchlistCounter++;
if(watchlistCounter >= watchlistManager.getWatchlist().size())
{
generateCards();
}
}
private View getCurrencyCardFor(final Currency currency)
{
final View card = LayoutInflater.from(getContext()).inflate(R.layout.cardview_watchlist, null);
card.setTag(currency.getSymbol());
((TextView) card.findViewById(R.id.currencyFluctuationTextView))
.setText(PlaceholderManager.getValueParenthesisString(numberConformer(currency.getDayFluctuation()), getActivity()));
((TextView) card.findViewById(R.id.currencyValueTextView))
.setText(PlaceholderManager.getValueString(numberConformer(currency.getValue()), getActivity()));
((TextView) card.findViewById(R.id.currencyFluctuationPercentageTextView))
.setText(PlaceholderManager.getPercentageString(numberConformer(currency.getDayFluctuationPercentage()), getActivity()));
((TextView) card.findViewById(R.id.currencyNameTextView))
.setText(currency.getName());
((TextView) card.findViewById(R.id.currencySymbolTextView))
.setText(PlaceholderManager.getSymbolString(currency.getSymbol(), getActivity()));
((ImageView) card.findViewById(R.id.currencyIcon)).setImageBitmap(currency.getIcon());
((LineChart) card.findViewById(R.id.LineChartView)).setNoDataTextColor(currency.getChartColor());
Drawable arrowDrawable = ((ImageView) card.findViewById(R.id.detailsArrow)).getDrawable();
arrowDrawable.mutate();
arrowDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
arrowDrawable.invalidateSelf();
Drawable progressDrawable = ((ProgressBar) card.findViewById(R.id.progressBarLinechartWatchlist)).getIndeterminateDrawable();
progressDrawable.mutate();
progressDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
progressDrawable.invalidateSelf();
card.findViewById(R.id.deleteCardWatchlist).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
collapse(card);
DatabaseManager databaseManager = new DatabaseManager(getActivity());
databaseManager.deleteCurrencyFromWatchlist(currency.getSymbol());
}
});
updateColor(card, currency);
card.findViewById(R.id.LineChartView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), CurrencyDetailsActivity.class);
intent.putExtra("currency", currency);
getActivity().getApplicationContext().startActivity(intent);
}
});
card.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
if(view.findViewById(R.id.collapsableLayout).getVisibility() == View.VISIBLE)
{
collapseView(view);
}
else
{
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.GONE);
view.findViewById(R.id.progressBarLinechartWatchlist).setVisibility(View.VISIBLE);
extendView(view);
if (currency.getHistoryMinutes() == null) {
currency.updateHistoryMinutes(getActivity(), preferencesManager.getDefaultCurrency(), new Currency.CurrencyCallBack() {
@Override
public void onSuccess(Currency currency) {
if(currency.getHistoryMinutes() != null)
{
setupLineChart(view, currency);
view.findViewById(R.id.progressBarLinechartWatchlist).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.VISIBLE);
}
else
{
view.findViewById(R.id.progressBarLinechartWatchlist).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.VISIBLE);
view.findViewById(R.id.linearLayoutSubLayout).findViewById(R.id.detailsArrow).setVisibility(View.GONE);
}
}
});
}
else
{
extendView(view);
view.findViewById(R.id.progressBarLinechartWatchlist).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.VISIBLE);
}
}
}
});
return card;
}
private LineData generateData(Currency currency)
{
LineDataSet dataSet;
List<CurrencyDataChart> dataChartList = currency.getHistoryMinutes();
ArrayList<Entry> values = new ArrayList<>();
for(int i = 0; i < dataChartList.size(); i+=10)
{
values.add(new Entry(i, (float) dataChartList.get(i).getOpen()));
}
dataSet = new LineDataSet(values, "History");
dataSet.setDrawIcons(false);
dataSet.setColor(currency.getChartColor());
dataSet.setLineWidth(1);
dataSet.setDrawFilled(true);
dataSet.setFillColor(getColorWithAplha(currency.getChartColor(), 0.5f));
dataSet.setFormLineWidth(1);
dataSet.setFormSize(15);
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setHighlightEnabled(false);
return new LineData(dataSet);
}
private int getColorWithAplha(int color, float ratio)
{
int transColor;
int alpha = Math.round(Color.alpha(color) * ratio);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
transColor = Color.argb(alpha, r, g, b);
return transColor ;
}
private void setupLineChart(View view, final Currency currency)
{
LineChart lineChart = view.findViewById(R.id.LineChartView);
lineChart.setDrawGridBackground(false);
lineChart.setDrawBorders(false);
lineChart.setDrawMarkers(false);
lineChart.setDoubleTapToZoomEnabled(false);
lineChart.setPinchZoom(false);
lineChart.setScaleEnabled(false);
lineChart.setDragEnabled(false);
lineChart.getDescription().setEnabled(false);
lineChart.getAxisLeft().setEnabled(false);
lineChart.getAxisRight().setEnabled(false);
lineChart.getLegend().setEnabled(false);
lineChart.getXAxis().setEnabled(false);
lineChart.setViewPortOffsets(0, 0, 0, 0);
lineChart.setData(generateData(currency));
lineChart.invalidate();
}
private void updateColor(View card, Currency currency)
{
if(currency.getDayFluctuation() >= 0)
{
((TextView) card.findViewById(R.id.currencyFluctuationPercentageTextView)).setTextColor(getResources().getColor(R.color.increase));
((TextView) card.findViewById(R.id.currencyFluctuationTextView)).setTextColor(getResources().getColor(R.color.increase));
}
else
{
((TextView) card.findViewById(R.id.currencyFluctuationPercentageTextView)).setTextColor(getResources().getColor(R.color.decrease));
((TextView) card.findViewById(R.id.currencyFluctuationTextView)).setTextColor(getResources().getColor(R.color.decrease));
}
}
private String getIconUrl(String symbol)
{
String url;
try {
JSONObject jsonObject = new JSONObject(currencyDetailsList.getCoinInfosHashmap().get(symbol));
url = "https://www.cryptocompare.com" + jsonObject.getString("ImageUrl") + "?width=50";
} catch (NullPointerException e) {
Log.d(getContext().getResources().getString(R.string.debug), symbol + " has no icon URL");
url = null;
} catch (JSONException e) {
Log.d(getContext().getResources().getString(R.string.debug), "Url parsing error for " + symbol);
url = null;
}
return url;
}
private void getBitmapFromURL(String src, HomeActivity.IconCallBack callBack) {
Bitmap result;
try {
java.net.URL url = new java.net.URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
result = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
result = BitmapFactory.decodeResource(this.getResources(),
R.mipmap.icon_coinfolio);
result = Bitmap.createScaledBitmap(result, 50, 50, false);
}
callBack.onSuccess(result);
}
private void updateChartColor(Currency currency)
{
if(currency.getIcon() != null)
{
Palette.Builder builder = Palette.from(currency.getIcon());
currency.setChartColor(builder.generate().getDominantColor(0));
}
else
{
currency.setChartColor(12369084);
}
}
public int getCurrencyId(String symbol)
{
int id = 0;
try {
JSONObject jsonObject = new JSONObject(currencyDetailsList.getCoinInfosHashmap().get(symbol));
id = jsonObject.getInt("Id");
} catch (JSONException e) {
e.printStackTrace();
}
return id;
}
private class WatchlistUpdater extends AsyncTask<Void, Integer, Void>
{
@Override
protected void onPreExecute()
{
watchlistCounter = 0;
}
@Override
protected Void doInBackground(Void... voids) {
for(final Currency currency : watchlistManager.getWatchlist())
{
currency.setTickerId(currencyTickerList.getTickerIdForSymbol(currency.getSymbol()));
currency.setId(getCurrencyId(currency.getSymbol()));
currency.updatePrice(getActivity(), preferencesManager.getDefaultCurrency(), new Currency.CurrencyCallBack() {
@Override
public void onSuccess(final Currency sucessCurrency) {
if(getIconUrl(sucessCurrency.getSymbol()) != null)
{
getBitmapFromURL(getIconUrl(sucessCurrency.getSymbol()), new HomeActivity.IconCallBack() {
@Override
public void onSuccess(Bitmap bitmapIcon) {
sucessCurrency.setIcon(bitmapIcon);
updateChartColor(currency);
countWatchlist();
}
});
}
}
});
}
return null;
}
}
private String numberConformer(double number)
{
String str;
if(abs(number) > 1)
{
str = String.format( Locale.UK, "%.2f", number).replaceAll("\\.?0*$", "");
}
else
{
str = String.format( Locale.UK, "%.4f", number).replaceAll("\\.?0*$", "");
}
int counter = 0;
int i = str.indexOf(".");
if(i <= 0)
{
i = str.length();
}
for(i -= 1; i > 0; i--)
{
counter++;
if(counter == 3)
{
str = str.substring(0, i) + " " + str.substring(i, str.length());
counter = 0;
}
}
return str;
}
}

View File

@ -1,136 +0,0 @@
package com.nauk.coinfolio.Activities;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TimePicker;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.DatabaseManager;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.R;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class RecordTransactionActivity extends AppCompatActivity {
private String coin;
private String symbol;
private EditText amountTxtView;
private TextView purchasedDate;
private Button validateButton;
private DatabaseManager databaseManager;
private Calendar calendar;
private SimpleDateFormat sdf;
private PreferencesManager preferenceManager;
private EditText purchasedPrice;
private Currency currency;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record_transaction);
Intent intent = getIntent();
coin = intent.getStringExtra("coin");
symbol = intent.getStringExtra("symbol");
setTitle("Add " + coin + " transaction");
sdf = new SimpleDateFormat(" HH:mm dd/MM/yyyy");
calendar = Calendar.getInstance();
currency = new Currency(coin, symbol);
databaseManager = new DatabaseManager(this);
preferenceManager = new PreferencesManager(this);
validateButton = findViewById(R.id.validateButton);
amountTxtView = findViewById(R.id.currencyAmount);
purchasedDate = findViewById(R.id.purchaseDate);
purchasedPrice = findViewById(R.id.purchasePrice);
//purchasedPrice.setText();
purchasedDate.setText(sdf.format(calendar.getTime()));
purchasedDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createDatePicker();
}
});
validateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
databaseManager.addCurrencyToManualCurrency(symbol, Double.parseDouble(amountTxtView.getText().toString()), calendar.getTime(), purchasedPrice.getText().toString());
preferenceManager.setMustUpdateSummary(true);
Intent intent = new Intent(RecordTransactionActivity.this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
finish();
}
});
currency.getTimestampPrice(this, preferenceManager.getDefaultCurrency(), new Currency.PriceCallBack() {
@Override
public void onSuccess(String price) {
purchasedPrice.setText(price);
}
}, calendar.getTimeInMillis() / 1000);
}
private void createDatePicker()
{
new android.app.DatePickerDialog(
RecordTransactionActivity.this,
new android.app.DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
purchasedDate.setText(sdf.format(calendar.getTime()));
createTimePicker();
}
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
).show();
}
private void createTimePicker()
{
new android.app.TimePickerDialog(
RecordTransactionActivity.this,
new android.app.TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hour, int minute) {
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
purchasedDate.setText(sdf.format(calendar.getTime()));
currency.getTimestampPrice(RecordTransactionActivity.this, preferenceManager.getDefaultCurrency(), new Currency.PriceCallBack() {
@Override
public void onSuccess(String price) {
purchasedPrice.setText(price);
}
}, calendar.getTimeInMillis() / 1000);
Log.d("coinfolio", "Time : " + calendar.getTimeInMillis());
}
},
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
true
).show();
}
}

View File

@ -1,500 +0,0 @@
package com.nauk.coinfolio.Activities;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.fingerprint.FingerprintManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBar;
import android.text.TextUtils;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import com.nauk.coinfolio.BuildConfig;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.FingerprintToolkit.FingerprintDialogFragment;
import com.nauk.coinfolio.FingerprintToolkit.FingerprintHandler;
import com.nauk.coinfolio.R;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
}
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|| DataSyncPreferenceFragment.class.getName().equals(fragmentName)
|| NotificationPreferenceFragment.class.getName().equals(fragmentName)
|| ExchangePreferenceFragment.class.getName().equals(fragmentName);
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
findPreference("hide_balance").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
boolean isChecked = ((SwitchPreference) findPreference("hide_balance")).isChecked();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("hide_balance", isChecked);
editor.apply();
return isChecked;
}
});
((PreferenceScreen) findPreference("version")).setSummary(BuildConfig.VERSION_NAME);
bindPreferenceSummaryToValue(findPreference("default_currency"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
//startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ExchangePreferenceFragment extends PreferenceFragment {
private static final String KEY_NAME = "NAUKEY";
private Cipher cipher;
private KeyStore keyStore;
private KeyGenerator keyGenerator;
private FingerprintManager.CryptoObject cryptoObject;
private FingerprintManager fingerprintManager;
private KeyguardManager keyguardManager;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_exchange);
setHasOptionsMenu(true);
bindPreferenceSummaryToValue(findPreference("hitbtc_publickey"));
bindPreferenceSummaryToValue(findPreference("binance_publickey"));
bindPreferenceSummaryToValue(findPreference("hitbtc_privatekey"));
bindPreferenceSummaryToValue(findPreference("binance_privatekey"));
findPreference("enable_hitbtc").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
boolean isChecked = ((SwitchPreference) findPreference("enable_hitbtc")).isChecked();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("mustUpdateSummary", true);
editor.apply();
return isChecked;
}
});
findPreference("enable_binance").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
boolean isChecked = ((SwitchPreference) findPreference("enable_binance")).isChecked();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("mustUpdateSummary", true);
editor.apply();
return isChecked;
}
});
startFingerprintProtocol();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
//startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
private void startFingerprintProtocol()
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getContext());
FingerprintDialogFragment newFragment = FingerprintDialogFragment.newInstance();
if(preferences.getBoolean("enable_fingerprint", false))
{
newFragment.setCancelable(false);
newFragment.show(getFragmentManager(), "dialog");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
keyguardManager = (KeyguardManager) this.getActivity().getSystemService(KEYGUARD_SERVICE);
fingerprintManager = (FingerprintManager) this.getActivity().getSystemService(FINGERPRINT_SERVICE);
try {
if(!fingerprintManager.isHardwareDetected())
{
this.getActivity().findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
}
if(ActivityCompat.checkSelfPermission(this.getContext(), Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED)
{
this.getActivity().findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
}
if(!fingerprintManager.hasEnrolledFingerprints())
{
this.getActivity().findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
}
if(!keyguardManager.isKeyguardSecure())
{
this.getActivity().findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
}
else
{
try {
generateKey();
} catch (FingerprintException e) {
e.printStackTrace();
}
if(initCipher())
{
cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this.getContext(), newFragment);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
}
private void generateKey() throws FingerprintException
{
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyStore.load(null);
keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (KeyStoreException
| NoSuchAlgorithmException
| NoSuchProviderException
| InvalidAlgorithmParameterException
| CertificateException
| IOException e) {
e.printStackTrace();
throw new FingerprintException(e);
}
}
public boolean initCipher()
{
try {
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("Failed to get Cipher", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException
| UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
private class FingerprintException extends Exception {
public FingerprintException(Exception e)
{
super(e);
}
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notification);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
/**
* This fragment shows data and sync preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class DataSyncPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_data_sync);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -1,351 +0,0 @@
package com.nauk.coinfolio.DataManagers;
import android.os.StrictMode;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyDetailsList;
import com.nauk.coinfolio.DataManagers.ExchangeManager.BinanceManager;
import com.nauk.coinfolio.DataManagers.ExchangeManager.HitBtcManager;
import com.nauk.coinfolio.R;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.regex.Pattern;
/**
* Created by Tiji on 25/12/2017.
*/
public class BalanceManager {
private String publicHitKey;
private String publicBinanceKey;
private String publicPoloniex;
private String privateHitKey;
private String privateBinanceKey;
private String privatePoloniex;
final private String hitBalanceUrl = "https://api.hitbtc.com/api/2/trading/balance";
final private String detailUrl = "https://www.cryptocompare.com/api/data/coinlist/";
private RequestQueue requestQueue;
private List<Currency> binanceBalance;
private List<Currency> hitBalance;
private List<Currency> manualBalances;
private List<Currency> totalBalance;
private android.content.Context context;
private LinkedHashMap<String, String> coinInfosHashmap;
private PreferencesManager preferenceManager;
private DatabaseManager databaseManager;
private CurrencyDetailsList currencyDetailsList;
private int balanceCounter;
//NEW IMPLEMENTATION
private List<HitBtcManager> hitBtcManagers;
private List<BinanceManager> binanceManagers;
public BalanceManager(android.content.Context context)
{
this.context = context;
preferenceManager = new PreferencesManager(context);
requestQueue = Volley.newRequestQueue(context);
binanceBalance = new ArrayList<Currency>();
hitBalance = new ArrayList<Currency>();
manualBalances = new ArrayList<Currency>();
databaseManager = new DatabaseManager(context);
hitBtcManagers = new ArrayList<>();
binanceManagers = new ArrayList<>();
currencyDetailsList = new CurrencyDetailsList(context);
balanceCounter = 0;
}
public List<String> getBiggestCurrencies()
{
List<String> currenciesDetails = new ArrayList<>();
int index = 0;
Iterator<String> coinIterator = currencyDetailsList.getCoinInfosHashmap().keySet().iterator();
while(index < 11)
{
index++;
Log.d("coinfolio", "For " + index + " : " + coinIterator.next());
}
return currenciesDetails;
}
public void updateExchangeKeys()
{
String publicKey = preferenceManager.getHitBTCPublicKey();
String privateKey = preferenceManager.getHitBTCPrivateKey();
hitBtcManagers.clear();
if(preferenceManager.isHitBTCActivated() && publicKey != null && privateKey != null)
{
hitBtcManagers.add(new HitBtcManager(context, publicKey, privateKey));
}
publicKey = preferenceManager.getBinancePublicKey();
privateKey = preferenceManager.getBinancePrivateKey();
binanceManagers.clear();
if(preferenceManager.isBinanceActivated() && publicKey != null && privateKey != null)
{
binanceManagers.add(new BinanceManager(publicKey, privateKey));
}
}
public List<Currency> getTotalBalance()
{
return totalBalance;
}
public void updateTotalBalance(final VolleyCallBack callBack)
{
boolean isUpdated = false;
balanceCounter = 0;
manualBalances = databaseManager.getAllCurrenciesFromManualCurrency();
if(binanceManagers.size() > 0)
{
isUpdated = true;
for(int i = 0; i < binanceManagers.size(); i++)
{
binanceManagers.get(i).updateBalance(new BinanceManager.BinanceCallBack() {
@Override
public void onSuccess() {
countBalances(callBack);
}
@Override
public void onError(String error) {
callBack.onError(error);
}
});
}
}
if(hitBtcManagers.size() > 0)
{
isUpdated = true;
for(int i = 0; i < hitBtcManagers.size(); i++)
{
hitBtcManagers.get(i).updateBalance(new HitBtcManager.HitBtcCallBack() {
@Override
public void onSuccess() {
countBalances(callBack);
}
@Override
public void onError(String error) {
callBack.onError(error);
}
});
}
}
if(!isUpdated)
{
refreshAllBalances(callBack);
}
}
private void countBalances(VolleyCallBack callBack)
{
balanceCounter++;
if(balanceCounter == hitBtcManagers.size() + binanceManagers.size())
{
refreshAllBalances(callBack);
balanceCounter = 0;
}
}
private void refreshAllBalances(final VolleyCallBack callBack)
{
totalBalance = new ArrayList<>();
for(int i = 0; i < hitBtcManagers.size(); i++)
{
mergeBalanceTotal(hitBtcManagers.get(i).getBalance());
}
for(int i = 0; i < binanceManagers.size(); i++)
{
mergeBalanceTotal(binanceManagers.get(i).getBalance());
}
mergeBalanceTotal(manualBalances);
callBack.onSuccess();
}
private void mergeBalanceTotal(List<Currency> balance)
{
if(balance != null)
{
for(int i = 0; i < balance.size(); i++)
{
boolean isIn = false;
for(int j = 0; j < totalBalance.size(); j++)
{
if(balance.get(i).getSymbol().equals(totalBalance.get(j).getSymbol()))
{
totalBalance.get(j).setBalance(totalBalance.get(j).getBalance() + balance.get(i).getBalance());
isIn = true;
}
}
if(!isIn)
{
totalBalance.add(balance.get(i));
}
}
}
}
public interface VolleyCallBack {
void onSuccess();
void onError(String error);
}
public interface IconCallBack {
void onSuccess();
}
public void sortCoins()
{
for(int i = 0; i < totalBalance.size(); i++)
{
for(int j = i; j < totalBalance.size(); j++)
{
if(totalBalance.get(j).getBalance() * totalBalance.get(j).getValue() > totalBalance.get(i).getBalance() * totalBalance.get(i).getValue())
{
Currency temp = totalBalance.get(j);
totalBalance.set(j, totalBalance.get(i));
totalBalance.set(i, temp);
}
}
}
}
public void updateDetails(final IconCallBack callBack)
{
currencyDetailsList.update(callBack);
/*StringRequest strRequest = new StringRequest(Request.Method.GET, detailUrl,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processDetailResult(response, callBack);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);*/
}
public String getIconUrl(String symbol)
{
String url;
try {
JSONObject jsonObject = new JSONObject(currencyDetailsList.getCoinInfosHashmap().get(symbol));
url = "https://www.cryptocompare.com" + jsonObject.getString("ImageUrl") + "?width=50";
} catch (NullPointerException e) {
Log.d(context.getResources().getString(R.string.debug), symbol + " has no icon URL");
url = null;
} catch (JSONException e) {
Log.d(context.getResources().getString(R.string.debug), "Url parsing error for " + symbol);
url = null;
}
return url;
}
public String getCurrencyName(String symbol)
{
String currencyName = null;
try {
JSONObject jsonObject = new JSONObject(currencyDetailsList.getCoinInfosHashmap().get(symbol));
currencyName = jsonObject.getString("CoinName");
} catch (JSONException e) {
e.printStackTrace();
}
return currencyName;
}
public int getCurrencyId(String symbol)
{
int id = 0;
try {
JSONObject jsonObject = new JSONObject(currencyDetailsList.getCoinInfosHashmap().get(symbol));
id = jsonObject.getInt("Id");
} catch (JSONException e) {
e.printStackTrace();
}
return id;
}
private void sortDetails()
{
LinkedHashMap<String, String> sortedHashmap = new LinkedHashMap<>();
List<String> listInfos = new ArrayList<>(coinInfosHashmap.values());
List<String> listSymbols = new ArrayList<>(coinInfosHashmap.keySet());
for(int i = 0; i < coinInfosHashmap.keySet().size(); i++)
{
try {
JSONObject jsonObject = new JSONObject(listInfos.get(i));
int index = jsonObject.getInt("SortOrder");
listInfos.add(index, listInfos.get(i));
listSymbols.add(index, listSymbols.get(i));
} catch (JSONException e) {
e.printStackTrace();
}
}
for(int i = 0; i < listInfos.size(); i++)
{
sortedHashmap.put(listSymbols.get(i), listInfos.get(i));
}
coinInfosHashmap = sortedHashmap;
}
}

View File

@ -1,149 +0,0 @@
package com.nauk.coinfolio.DataManagers.CurrencyData;
import android.os.StrictMode;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.nauk.coinfolio.Activities.HomeActivity;
import com.nauk.coinfolio.DataManagers.BalanceManager;
import com.nauk.coinfolio.R;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.regex.Pattern;
/**
* Created by Tiji on 11/04/2018.
*/
public class CurrencyDetailsList {
final private static String DETAILURL = "https://www.cryptocompare.com/api/data/coinlist/";
private RequestQueue requestQueue;
private LinkedHashMap<String, String> coinInfosHashmap;
private android.content.Context context;
public CurrencyDetailsList(android.content.Context context)
{
this.context = context;
requestQueue = Volley.newRequestQueue(context);
}
public void update(final BalanceManager.IconCallBack callBack)
{
StringRequest strRequest = new StringRequest(Request.Method.GET, DETAILURL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processDetailResult(response, callBack);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
private void processDetailResult(String response, final BalanceManager.IconCallBack callBack)
{
response = response.substring(response.indexOf("\"Data\"") + 7, response.lastIndexOf("},\"Type\":100}"));
String[] tab = response.split(Pattern.quote("},"));
coinInfosHashmap = new LinkedHashMap<>();
for(int i = 0; i < tab.length; i++)
{
tab[i] = tab[i].substring(tab[i].indexOf("\":{")+2, tab[i].length()) + "}";
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
JSONObject jsonObject = new JSONObject(tab[i]);
coinInfosHashmap.put(jsonObject.getString("Symbol"), tab[i]);
} catch (JSONException e) {
Log.d(context.getResources().getString(R.string.debug), "ImageUrl not found.");
}
}
sortDetails();
callBack.onSuccess();
}
private void sortDetails()
{
LinkedHashMap<String, String> sortedHashmap = new LinkedHashMap<>();
List<String> listInfos = new ArrayList<>(coinInfosHashmap.values());
List<String> listSymbols = new ArrayList<>(coinInfosHashmap.keySet());
for(int i = 0; i < coinInfosHashmap.keySet().size(); i++)
{
try {
JSONObject jsonObject = new JSONObject(listInfos.get(i));
int index = jsonObject.getInt("SortOrder");
listInfos.add(index, listInfos.get(i));
listSymbols.add(index, listSymbols.get(i));
} catch (JSONException e) {
e.printStackTrace();
}
}
for(int i = 0; i < listInfos.size(); i++)
{
sortedHashmap.put(listSymbols.get(i), listInfos.get(i));
}
coinInfosHashmap = sortedHashmap;
}
public LinkedHashMap<String, String> getCoinInfosHashmap() {
return coinInfosHashmap;
}
public List<String> getCurrenciesName()
{
List<String> currenciesName = new ArrayList<>();
for (String symbol : coinInfosHashmap.keySet())
{
try {
JSONObject jsonObject = new JSONObject(coinInfosHashmap.get(symbol));
currenciesName.add(jsonObject.getString("CoinName"));
} catch (JSONException e) {
e.printStackTrace();
}
}
return currenciesName;
}
public Currency getCurrencyDetailsFromSymbol(String symbol)
{
//Currency currency = new Currency();
return null;
}
public List<String> getCurrenciesSymbol()
{
return new ArrayList<>(coinInfosHashmap.keySet());
}
}

View File

@ -1,101 +0,0 @@
package com.nauk.coinfolio.DataManagers.CurrencyData;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.nauk.coinfolio.DataManagers.BalanceManager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.LinkedHashMap;
import java.util.regex.Pattern;
/**
* Created by Guitoune on 22/04/2018.
*/
public class CurrencyTickerList {
final private static String TICKERLISTURL = "https://api.coinmarketcap.com/v1/ticker/?limit=0";
private RequestQueue requestQueue;
private LinkedHashMap<String, String> coinTickersHashmap;
private android.content.Context context;
public CurrencyTickerList(android.content.Context context)
{
this.context = context;
requestQueue = Volley.newRequestQueue(context);
}
public void update(final BalanceManager.IconCallBack callBack)
{
coinTickersHashmap = new LinkedHashMap<>();
StringRequest strRequest = new StringRequest(Request.Method.GET, TICKERLISTURL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processTickerListResult(response, callBack);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
public String getTickerIdForSymbol(String symbol)
{
String tickerId = null;
try {
JSONObject jsonObject = new JSONObject(coinTickersHashmap.get(symbol));
tickerId = jsonObject.getString("id");
} catch (JSONException | NullPointerException e) {
e.printStackTrace();
}
return tickerId;
}
public void processTickerListResult(String response, BalanceManager.IconCallBack callBack)
{
response = response.substring(1, response.length() - 1);
String[] strTable = response.split(Pattern.quote("},"));
for(int i = 0; i < strTable.length; i++)
{
strTable[i] += "}";
try {
JSONObject jsonObject = new JSONObject(strTable[i]);
switch (jsonObject.getString("symbol"))
{
case "MIOTA":
coinTickersHashmap.put("IOT", strTable[i]);
break;
case "NANO":
coinTickersHashmap.put("XRB", strTable[i]);
break;
default:
coinTickersHashmap.put(jsonObject.getString("symbol"), strTable[i]);
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
callBack.onSuccess();
}
}

View File

@ -1,63 +0,0 @@
package com.nauk.coinfolio.DataManagers.CurrencyData;
/**
* Created by Guitoune on 30/01/2018.
*/
public class Transaction {
private int transactionId;
private String symbol;
private double amount;
private long timestamp;
private double purchasedPrice;
private boolean isMined;
public Transaction(int transactionId, String symbol, double amount, long timestamp, double purchasedPrice)
{
this.transactionId = transactionId;
this.symbol = symbol;
this.amount = amount;
this.timestamp = timestamp;
this.purchasedPrice = purchasedPrice;
}
public int getTransactionId() {
return transactionId;
}
public void setTransactionId(int transactionId) {
this.transactionId = transactionId;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public double getAmount() {
return amount;
}
public long getTimestamp()
{
return timestamp;
}
public void setAmount(double amount) {
this.amount = amount;
}
public void setPurchasedPrice(double purchasedPrice)
{
this.purchasedPrice = purchasedPrice;
}
public double getPurchasedPrice()
{
return purchasedPrice;
}
}

View File

@ -1,191 +0,0 @@
package com.nauk.coinfolio.DataManagers;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.Transaction;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Created by Guitoune on 14/01/2018.
*/
public class DatabaseManager extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 6;
private static final String DATABASE_NAME = "Currencies.db";
private static final String TABLE_MANUAL_CURRENCIES = "ManualCurrencies";
private static final String TABLE_EXCHANGE_KEYS = "ExchangeKeys";
private static final String TABLE_WATCHLIST = "Watchlist";
private static final String KEY_CURRENCY_ID = "idCurrency";
private static final String KEY_CURRENCY_SYMBOL = "symbol";
private static final String KEY_CURRENCY_NAME = "name";
private static final String KEY_CURRENCY_BALANCE = "balance";
private static final String KEY_CURRENCY_DATE = "addDate";
private static final String KEY_CURRENCY_PURCHASED_PRICE = "purchasedPrice";
private static final String KEY_CURRENCY_IS_MINED = "isMined";
private static final String KEY_EXCHANGE_ID = "idExchange";
private static final String KEY_EXCHANGE_NAME = "name";
private static final String KEY_EXCHANGE_PUBLIC_KEY = "publicKey";
private static final String KEY_EXCHANGE_SECRET_KEY = "secretKey";
private static final String KEY_WATCHLIST_ID = "idWatchlist";
private static final String KEY_WATCHLIST_SYMBOL = "symbol";
private static final String KEY_WATCHLIST_NAME = "name";
private static final String KEY_WATCHLIST_POSITION = "position";
public DatabaseManager(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_MANUAL_CURRENCIES + "("
+ KEY_CURRENCY_ID + " INTEGER PRIMARY KEY,"
+ KEY_CURRENCY_SYMBOL + " VARCHAR(4),"
+ KEY_CURRENCY_NAME + " VARCHAR(45),"
+ KEY_CURRENCY_BALANCE + " TEXT,"
+ KEY_CURRENCY_DATE + " TEXT,"
+ KEY_CURRENCY_PURCHASED_PRICE + " REAL,"
+ KEY_CURRENCY_IS_MINED + " INTEGER"
+ ");");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_EXCHANGE_KEYS + "("
+ KEY_EXCHANGE_ID + " INTEGER PRIMARY KEY,"
+ KEY_EXCHANGE_NAME + " TEXT,"
+ KEY_EXCHANGE_PUBLIC_KEY + " TEXT,"
+ KEY_EXCHANGE_SECRET_KEY + " TEXT"
+ ");");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_WATCHLIST + "("
+ KEY_WATCHLIST_ID + " INTEGER PRIMARY KEY,"
+ KEY_WATCHLIST_SYMBOL + " VARCHAR(4),"
+ KEY_WATCHLIST_NAME + " TEXT,"
+ KEY_WATCHLIST_POSITION + " INTEGER"
+ ");");
//loadSample(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS " + TABLE_MANUAL_CURRENCIES);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_EXCHANGE_KEYS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_WATCHLIST);
onCreate(db);
}
public void addCurrencyToWatchlist(Currency currency)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_WATCHLIST_SYMBOL, currency.getSymbol());
values.put(KEY_WATCHLIST_NAME, currency.getName());
db.insert(TABLE_WATCHLIST, null, values);
db.close();
}
public int deleteCurrencyFromWatchlist(String symbol)
{
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TABLE_WATCHLIST, KEY_WATCHLIST_SYMBOL + " = '" + symbol + "'", null);
}
public List<Currency> getAllCurrenciesFromWatchlist()
{
String searchQuerry = "SELECT * FROM " + TABLE_WATCHLIST;
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultatList = db.rawQuery(searchQuerry, null);
List<Currency> currencyList = new ArrayList<>();
while(resultatList.moveToNext())
{
currencyList.add(new Currency(resultatList.getString(2), resultatList.getString(1)));
}
return currencyList;
}
public void addCurrencyToManualCurrency(String symbol, double balance, Date date, String purchasedPrice)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_CURRENCY_SYMBOL, symbol);
values.put(KEY_CURRENCY_BALANCE, balance);
values.put(KEY_CURRENCY_DATE, date.getTime());
values.put(KEY_CURRENCY_PURCHASED_PRICE, purchasedPrice);
db.insert(TABLE_MANUAL_CURRENCIES, null, values);
db.close();
}
public List<Currency> getAllCurrenciesFromManualCurrency()
{
String searchQuerry = "SELECT * FROM " + TABLE_MANUAL_CURRENCIES;
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultatList = db.rawQuery(searchQuerry, null);
List<Currency> currencyList = new ArrayList<>();
while(resultatList.moveToNext())
{
currencyList.add(new Currency(resultatList.getString(1), resultatList.getDouble(3)));
}
resultatList.close();
db.close();
return currencyList;
}
public List<Transaction> getCurrencyTransactions(String symbol)
{
String searchQuerry = "SELECT * FROM " + TABLE_MANUAL_CURRENCIES + " WHERE symbol='" + symbol.toUpperCase() + "'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor resultatList = db.rawQuery(searchQuerry, null);
List<Transaction> transactionList = new ArrayList<>();
while(resultatList.moveToNext())
{
transactionList.add(new Transaction(resultatList.getInt(0), resultatList.getString(1), resultatList.getDouble(3), resultatList.getLong(4), resultatList.getLong(5)));
}
resultatList.close();
db.close();
return transactionList;
}
public void deleteTransactionFromId(int id)
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_MANUAL_CURRENCIES, KEY_CURRENCY_ID + "=" + id, null);
db.close();
}
}

View File

@ -1,120 +0,0 @@
package com.nauk.coinfolio.DataManagers.ExchangeManager;
import android.util.Log;
import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.BinanceApiRestClient;
import com.binance.api.client.domain.account.Account;
import com.binance.api.client.domain.account.AssetBalance;
import com.binance.api.client.domain.account.Order;
import com.binance.api.client.domain.account.Trade;
import com.binance.api.client.domain.account.request.OrderRequest;
import com.binance.api.client.exception.BinanceApiException;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Guitoune on 26/02/2018.
*/
public class BinanceManager {
private String publicKey;
private String privateKey;
private List<Currency> balance;
private HashMap<String, List<Trade>> trades;
public BinanceManager(String publicKey, String privateKey)
{
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public void updateBalance(BinanceCallBack callBack)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(publicKey, privateKey);
BinanceApiRestClient client = factory.newRestClient();
try {
Account account = client.getAccount();
List<AssetBalance> assets = account.getBalances();
balance = new ArrayList<>();
for(int i = 0; i < assets.size(); i++)
{
if(Double.parseDouble(assets.get(i).getFree()) > 0 || Double.parseDouble(assets.get(i).getLocked()) > 0)
{
balance.add(new Currency(assets.get(i).getAsset(), Double.parseDouble(assets.get(i).getFree()) + Double.parseDouble(assets.get(i).getLocked())));
}
}
callBack.onSuccess();
} catch (BinanceApiException e) {
callBack.onError(e.getMessage());
}
}
public void updateTrades(BinanceCallBack callBack, String symbol)
{
trades = new HashMap<>();
trades.put("BTC", updateTrades(null, symbol, "BTC"));
trades.put("ETH", updateTrades(null, symbol, "ETH"));
trades.put("USDT", updateTrades(null, symbol, "USDT"));
callBack.onSuccess();
}
public List<Trade> updateTrades(BinanceCallBack callBack, String symbol, String pairSymbol)
{
List<Trade> presentTrades = new ArrayList<>();
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(publicKey, privateKey);
BinanceApiRestClient client = factory.newRestClient();
if(!symbol.equals(pairSymbol))
{
try {
presentTrades = client.getMyTrades(symbol + pairSymbol, 20);
} catch (BinanceApiException e) {
try {
presentTrades = client.getMyTrades(pairSymbol + symbol);
} catch (BinanceApiException f) {
f.printStackTrace();
}
}
}
if(callBack != null)
{
callBack.onSuccess();
}
return presentTrades;
}
public List<Currency> getBalance()
{
return balance;
}
public HashMap<String, List<Trade>> getTrades()
{
return trades;
}
public interface BinanceCallBack {
void onSuccess();
void onError(String error);
}
}

View File

@ -1,122 +0,0 @@
package com.nauk.coinfolio.DataManagers.ExchangeManager;
import android.util.Base64;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Guitoune on 26/02/2018.
*/
public class HitBtcManager {
private String publicKey;
private String privateKey;
final private String hitBalanceUrl = "https://api.hitbtc.com/api/2/trading/balance";
private RequestQueue requestQueue;
private List<Currency> balance;
private android.content.Context context;
public HitBtcManager(android.content.Context context, String publicKey, String privateKey)
{
this.context = context;
requestQueue = Volley.newRequestQueue(context);
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public void updateBalance(final HitBtcCallBack callBack)
{
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.GET, hitBalanceUrl
, getResponseListener(callBack), getErrorResponseListener(callBack))
{
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String credentials = publicKey + ":" + privateKey;
String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Content-Type", "application/json");
headers.put("Authorization", auth);
return headers;
}
};
requestQueue.add(arrayRequest);
}
private Response.Listener<JSONArray> getResponseListener(final HitBtcCallBack callBack)
{
return new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
if (response.length() > 0) {
parseBalance(response);
}
callBack.onSuccess();
}
};
}
private Response.ErrorListener getErrorResponseListener(final HitBtcCallBack callBack)
{
return new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(context.getResources().getString(R.string.debug), "API Error : " + error);
callBack.onError(error.toString());
}
};
}
private void parseBalance(JSONArray response)
{
balance = new ArrayList<>();
for(int i = 0; i < response.length(); i++)
{
try {
JSONObject jsonObject = response.getJSONObject(i);
if(Float.parseFloat(jsonObject.getString("available")) > 0)
{
balance.add(new Currency(jsonObject.getString("currency"), Double.parseDouble(jsonObject.getString("available"))));
}
} catch (JSONException e) {
Log.e(context.getResources().getString(R.string.debug), "Invalid JSON Object");
}
}
}
public List<Currency> getBalance()
{
return balance;
}
public interface HitBtcCallBack {
void onSuccess();
void onError(String error);
}
}

View File

@ -1,153 +0,0 @@
package com.nauk.coinfolio.DataManagers;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.regex.Pattern;
/**
* Created by Guitoune on 02/03/2018.
*/
public class MarketCapManager {
private static final String topCurrenciesUrl = "https://api.coinmarketcap.com/v1/ticker/?limit=9&convert=";
private static final String marketCapUrl = "https://api.coinmarketcap.com/v1/global/?convert=";
private RequestQueue requestQueue;
private String topRequestResult[];
private long marketCap;
private long dayVolume;
public MarketCapManager(android.content.Context context)
{
requestQueue = Volley.newRequestQueue(context);
}
public void updateTopCurrencies(final VolleyCallBack callBack, final String toSymbol)
{
String requestString = topCurrenciesUrl + toSymbol;
StringRequest strRequest = new StringRequest(Request.Method.GET, requestString,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processTopCurrencies(response, toSymbol);
}
callBack.onSuccess();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
public void updateMarketCap(final VolleyCallBack callBack, final String toSymbol)
{
String requestString = marketCapUrl + toSymbol;
StringRequest strRequest = new StringRequest(Request.Method.GET, requestString,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 0) {
processMarketCapData(response, toSymbol);
}
callBack.onSuccess();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(strRequest);
}
private void processMarketCapData(String response, String toSymbol)
{
try {
JSONObject jsonObject = new JSONObject(response);
marketCap = new BigDecimal(jsonObject.getString("total_market_cap_" + toSymbol.toLowerCase())).longValue();
dayVolume = new BigDecimal(jsonObject.getString("total_24h_volume_" + toSymbol.toLowerCase())).longValue();
} catch (JSONException e) {
e.printStackTrace();
}
}
public HashMap<String, Float> getDominance(String toSymbol)
{
HashMap<String, Float> dominance = new HashMap<>();
for(int i = 0; i < topRequestResult.length; i++)
{
try {
JSONObject jsonObject = new JSONObject(topRequestResult[i]);
dominance.put(jsonObject.getString("symbol"), (Float.parseFloat(jsonObject.getString("market_cap_" + toSymbol.toLowerCase())) / marketCap)*100);
} catch (JSONException e) {
e.printStackTrace();
}
}
return dominance;
}
public long getDayVolume()
{
return dayVolume;
}
private void processTopCurrencies(String response, String toSymbol)
{
response = response.substring(response.indexOf('[')+1, response.lastIndexOf(']'));
topRequestResult = response.split(Pattern.quote("},"));
for(int i = 0; i < topRequestResult.length; i++)
{
topRequestResult[i] += "}";
/*try {
JSONObject jsonObject = new JSONObject(topRequestResult[i]);
//Log.d("coinfolio", "Symbol : " + jsonObject.getString("symbol") + " " + jsonObject.getString("rank"));
} catch (JSONException e) {
e.printStackTrace();
}*/
}
}
public long getMarketCap()
{
return marketCap;
}
public interface VolleyCallBack
{
void onSuccess();
}
}

View File

@ -1,114 +0,0 @@
package com.nauk.coinfolio.LayoutManagers;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.R;
import java.util.ArrayList;
/**
* Created by Guitoune on 17/01/2018.
*/
public class CurrencyListAdapter extends ArrayAdapter<Currency> {
private ArrayList<Currency> tempCurrency, suggestions;
private Context context;
public CurrencyListAdapter(Context context, ArrayList<Currency> objects) {
super(context, android.R.layout.simple_list_item_1, objects);
this.tempCurrency = new ArrayList<Currency>(objects);
this.suggestions = new ArrayList<Currency>(objects);
this.context = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
Currency currency = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_currency_row, parent, false);
}
TextView currencyName = convertView.findViewById(R.id.currencyName);
TextView currencySymbol = convertView.findViewById(R.id.currencySymbol);
if (currencyName != null)
currencyName.setText(currency.getName());
if(currencySymbol != null)
{
currencySymbol.setText(currency.getSymbol());
}
if (position % 2 == 0)
convertView.setBackgroundColor(context.getResources().getColor(R.color.listBackground2));
else
convertView.setBackgroundColor(context.getResources().getColor(R.color.listBackground));
return convertView;
}
@Override
public Filter getFilter() {
return myFilter;
}
Filter myFilter = new Filter() {
@Override
public CharSequence convertResultToString(Object resultValue) {
Currency currency = (Currency) resultValue;
return currency.getName();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
suggestions.clear();
int i = 0;
int found = 0;
String temp = constraint.toString().toLowerCase();
while(i < tempCurrency.size() && found < 50)
{
Currency currency = tempCurrency.get(i);
if (currency.getName().toLowerCase().startsWith(temp)
|| currency.getSymbol().toLowerCase().startsWith(temp)) {
suggestions.add(currency);
found++;
}
i++;
}
FilterResults filterResults = new FilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
} else {
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
ArrayList<Currency> c = (ArrayList<Currency>) results.values;
if (results != null && results.count > 0) {
clear();
for (Currency currency : c) {
add(currency);
notifyDataSetChanged();
}
}
}
};
}

View File

@ -1,372 +0,0 @@
package com.nauk.coinfolio.LayoutManagers;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.preference.PreferenceScreen;
import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.nauk.coinfolio.Activities.CurrencyDetailsActivity;
import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyDataChart;
import com.nauk.coinfolio.DataManagers.PreferencesManager;
import com.nauk.coinfolio.PlaceholderManager;
import com.nauk.coinfolio.R;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import static java.lang.Math.abs;
/**
* Created by Tiji on 05/01/2018.
*/
public class HomeLayoutGenerator {
private android.content.Context context;
public HomeLayoutGenerator(Context context)
{
this.context = context;
}
public View getInfoLayout(final Currency currency, float totalValue, boolean isBalanceHidden)
{
View view = LayoutInflater.from(context).inflate(R.layout.cardview_currency, null, true);
((LineChart) view.findViewById(R.id.LineChartView)).setNoDataTextColor(currency.getChartColor());
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
PreferencesManager preferencesManager = new PreferencesManager(context);
if (view.findViewById(R.id.collapsableLayout).getVisibility() == View.VISIBLE) {
collapseView(view);
} else {
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.GONE);
view.findViewById(R.id.progressBarLinechartSummary).setVisibility(View.VISIBLE);
extendView(view);
if (currency.getHistoryMinutes() == null) {
currency.updateHistoryMinutes(context, preferencesManager.getDefaultCurrency(), new Currency.CurrencyCallBack() {
@Override
public void onSuccess(Currency currency) {
if(currency.getHistoryMinutes() != null)
{
setupLineChart(view, currency);
view.findViewById(R.id.progressBarLinechartSummary).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.VISIBLE);
}
else
{
view.findViewById(R.id.progressBarLinechartSummary).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.VISIBLE);
view.findViewById(R.id.linearLayoutSubLayout).findViewById(R.id.detailsArrow).setVisibility(View.GONE);
}
}
});
}
else
{
extendView(view);
view.findViewById(R.id.progressBarLinechartSummary).setVisibility(View.GONE);
view.findViewById(R.id.linearLayoutSubLayout).setVisibility(View.VISIBLE);
}
}
}
});
updateCardViewInfos(view, currency, totalValue, isBalanceHidden);
view.findViewById(R.id.LineChartView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(context.getApplicationContext(), CurrencyDetailsActivity.class);
intent.putExtra("currency", currency);
context.getApplicationContext().startActivity(intent);
}
});
updateColor(view, currency);
return view;
}
/*private class ChartLoader extends AsyncTask<Void, Integer, Void>
{
private View view;
private Currency currency;
ChartLoader(View view, Currency currency)
{
this.view = view;
this.currency = currency;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
extendView(view);
}
@Override
protected Void doInBackground(Void... voids) {
setupLineChart(view, currency);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
view.findViewById(R.id.progressLineChart).setVisibility(View.GONE);
view.findViewById(R.id.LineChartView).setVisibility(View.VISIBLE);
view.findViewById(R.id.LineChartView).invalidate();
}
}
*/
private static void expand(final View v) {
v.measure(CardView.LayoutParams.MATCH_PARENT, CardView.LayoutParams.WRAP_CONTENT);
final int targetHeight = v.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? CardView.LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
private static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
private void setupLineChart(View view, final Currency currency)
{
LineChart lineChart = view.findViewById(R.id.LineChartView);
lineChart.setDrawGridBackground(false);
lineChart.setDrawBorders(false);
lineChart.setDrawMarkers(false);
lineChart.setDoubleTapToZoomEnabled(false);
lineChart.setPinchZoom(false);
lineChart.setScaleEnabled(false);
lineChart.setDragEnabled(false);
lineChart.getDescription().setEnabled(false);
lineChart.getAxisLeft().setEnabled(false);
lineChart.getAxisRight().setEnabled(false);
lineChart.getLegend().setEnabled(false);
lineChart.getXAxis().setEnabled(false);
lineChart.setViewPortOffsets(0, 0, 0, 0);
lineChart.setData(generateData(currency));
}
private void updateCardViewInfos(View view, Currency currency, float totalValue, boolean isBalanceHidden)
{
double value = currency.getValue() * currency.getBalance();
double percentage = value / totalValue * 100;
DecimalFormat df = new DecimalFormat(".##");
((TextView) view.findViewById(R.id.currencyValueOwnedTextView))
.setText(PlaceholderManager.getValueParenthesisString(numberConformer(currency.getValue() * currency.getBalance()), context));
((TextView) view.findViewById(R.id.currencyValueTextView))
.setText(PlaceholderManager.getValueString(numberConformer(currency.getValue()), context));
((TextView) view.findViewById(R.id.currencyFluctuationTextView))
.setText(PlaceholderManager.getValueParenthesisString(numberConformer(currency.getDayFluctuation()), context));
((ImageView) view.findViewById(R.id.currencyIcon))
.setImageBitmap(currency.getIcon());
((TextView) view.findViewById(R.id.currencyNameTextView))
.setText(currency.getName());
((TextView) view.findViewById(R.id.currencySymbolTextView))
.setText(PlaceholderManager.getSymbolString(currency.getSymbol(), context));
((TextView) view.findViewById(R.id.currencyOwnedTextView))
.setText(PlaceholderManager.getBalanceString(numberConformer(currency.getBalance()), currency.getSymbol(), context));
((TextView) view.findViewById(R.id.currencyFluctuationPercentageTextView))
.setText(PlaceholderManager.getPercentageString(numberConformer(currency.getDayFluctuationPercentage()), context));
Drawable arrowDrawable = ((ImageView) view.findViewById(R.id.detailsArrow)).getDrawable();
arrowDrawable.mutate();
arrowDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
arrowDrawable.invalidateSelf();
Drawable progressDrawable = ((ProgressBar) view.findViewById(R.id.progressBarLinechartSummary)).getIndeterminateDrawable();
progressDrawable.mutate();
progressDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
progressDrawable.invalidateSelf();
Drawable progressBarDrawable = ((ProgressBar) view.findViewById(R.id.currencyPortfolioDominance)).getProgressDrawable();
progressBarDrawable.mutate();
progressBarDrawable.setColorFilter(new PorterDuffColorFilter(currency.getChartColor(), PorterDuff.Mode.SRC_IN));
progressBarDrawable.invalidateSelf();
((ProgressBar) view.findViewById(R.id.currencyPortfolioDominance)).setProgress((int) Math.round(percentage));
((TextView) view.findViewById(R.id.percentageOwnedTextView)).setText(PlaceholderManager.getPercentageString(numberConformer(percentage), context));
if(isBalanceHidden)
{
view.findViewById(R.id.currencyPortfolioDominance).setVisibility(View.VISIBLE);
view.findViewById(R.id.percentageOwnedTextView).setVisibility(View.VISIBLE);
view.findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.GONE);
}
else
{
view.findViewById(R.id.currencyPortfolioDominance).setVisibility(View.INVISIBLE);
view.findViewById(R.id.percentageOwnedTextView).setVisibility(View.GONE);
view.findViewById(R.id.currencyOwnedInfoLayout).setVisibility(View.VISIBLE);
}
}
private void collapseView(View view)
{
collapse(view.findViewById(R.id.collapsableLayout));
}
private void extendView(View view)
{
expand(view.findViewById(R.id.collapsableLayout));
//view.findViewById(R.id.LineChartView).invalidate();
}
private void updateColor(View view, Currency currency)
{
if(currency.getDayFluctuationPercentage() >= 0)
{
((TextView) view.findViewById(R.id.currencyFluctuationPercentageTextView))
.setTextColor(context.getResources().getColor(R.color.increase));
((TextView) view.findViewById(R.id.currencyFluctuationTextView))
.setTextColor(context.getResources().getColor(R.color.increase));
}
else
{
((TextView) view.findViewById(R.id.currencyFluctuationPercentageTextView))
.setTextColor(context.getResources().getColor(R.color.decrease));
((TextView) view.findViewById(R.id.currencyFluctuationTextView))
.setTextColor(context.getResources().getColor(R.color.decrease));
}
}
private LineData generateData(Currency currency)
{
LineDataSet dataSet;
List<CurrencyDataChart> dataChartList = currency.getHistoryMinutes();
ArrayList<Entry> values = new ArrayList<>();
for(int i = 0; i < dataChartList.size(); i+=10)
{
values.add(new Entry(i, (float) dataChartList.get(i).getOpen()));
}
dataSet = new LineDataSet(values, "History");
dataSet.setDrawIcons(false);
dataSet.setColor(currency.getChartColor());
dataSet.setLineWidth(1);
dataSet.setDrawFilled(true);
dataSet.setFillColor(getColorWithAplha(currency.getChartColor(), 0.5f));
dataSet.setFormLineWidth(1);
dataSet.setFormSize(15);
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setHighlightEnabled(false);
return new LineData(dataSet);
}
private int getColorWithAplha(int color, float ratio)
{
int transColor;
int alpha = Math.round(Color.alpha(color) * ratio);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
transColor = Color.argb(alpha, r, g, b);
return transColor ;
}
private String numberConformer(double number)
{
String str;
if(abs(number) > 1)
{
str = String.format( Locale.UK, "%.2f", number).replaceAll("\\.?0*$", "");
}
else
{
str = String.format( Locale.UK, "%.4f", number).replaceAll("\\.?0*$", "");
}
int counter = 0;
for(int i = str.indexOf(".") - 1; i > 0; i--)
{
counter++;
if(counter == 3)
{
str = str.substring(0, i) + " " + str.substring(i, str.length());
counter = 0;
}
}
return str;
}
}

View File

@ -1,47 +0,0 @@
package com.nauk.coinfolio;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import com.nauk.coinfolio.Activities.HomeActivityFragments.MarketCapitalization;
import com.nauk.coinfolio.Activities.HomeActivityFragments.Summary;
import com.nauk.coinfolio.Activities.HomeActivityFragments.Watchlist;
/**
* Created by Tiji on 13/04/2018.
*/
public class PagerAdapter extends FragmentStatePagerAdapter {
private int numOfTabs;
public PagerAdapter(FragmentManager fm, int numOfTabs)
{
super(fm);
this.numOfTabs = numOfTabs;
}
@Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
Watchlist watchlist = new Watchlist();
return watchlist;
case 1:
Summary summary = new Summary();
return summary;
case 2:
MarketCapitalization marketCapitalization = new MarketCapitalization();
return marketCapitalization;
default:
return null;
}
}
@Override
public int getCount() {
return numOfTabs;
}
}

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="500"
android:fromXDelta="100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
</set>

Some files were not shown because too many files have changed in this diff Show More