42 Commits

Author SHA1 Message Date
c01420a3c6 Nogroup if unchecked country 2024-04-10 21:48:57 +02:00
445cd05800 Fix case autogroup 2024-04-10 21:23:04 +02:00
d1f7c72adb Fixed icon 2024-04-10 21:09:44 +02:00
9228556ed1 Fixes 2024-04-10 21:06:42 +02:00
cd7c54230e CleanUp, Opti, Svg, ... 2024-04-10 20:56:14 +02:00
98582732cd Fix regions not colored in regional mode 2024-04-10 16:50:18 +02:00
ca16a0d20f Use better icons for light theme 2024-04-10 13:14:09 +02:00
99c7f8394c Enable group color change in single group setting 2024-04-10 13:08:49 +02:00
98591691a3 Correct bug when disabling and re-enabling regions 2024-04-10 11:20:08 +02:00
16faddb602 Merge pull request 'Update plugin com.mikepenz.aboutlibraries.plugin to v11.1.3' (#55) from renovate/com.mikepenz.aboutlibraries.plugin-11.x into main
Reviewed-on: #55
2024-04-10 08:36:47 +02:00
4dc3794b7e Merge pull request 'Update dependency com.mikepenz:aboutlibraries to v11.1.3' (#54) from renovate/com.mikepenz-aboutlibraries-11.x into main
Reviewed-on: #54
2024-04-10 08:36:38 +02:00
129d50c61d Update plugin com.mikepenz.aboutlibraries.plugin to v11.1.3 2024-04-10 00:01:23 +00:00
b51c714bfa Update dependency com.mikepenz:aboutlibraries to v11.1.3 2024-04-10 00:01:18 +00:00
63eed7bf59 Delete color 2024-04-10 00:11:40 +02:00
261d5eed5b Logo 2024-04-10 00:08:12 +02:00
494d58034d Choose map projection in settings 2024-04-09 22:29:26 +02:00
e87f2fac28 Better SVG 2024-04-09 19:27:16 +02:00
fd0ae64c0d Compute sum and ratio in stats 2024-04-09 16:51:00 +02:00
6aef6dabb2 Repair edit fragment refresh when groups are active 2024-04-09 13:52:08 +02:00
91574f4060 Correct some region names 2024-04-09 13:47:06 +02:00
8b2b694a00 Improved Stats 2024-04-09 08:29:53 +02:00
fbeefa0276 WIP Stats 2024-04-09 01:43:41 +02:00
cd999c2a6e Fixed Duplicate items in geoloc children 2024-04-09 00:03:34 +02:00
728994a8f3 Fix racecondition when button spam 2024-04-08 23:46:58 +02:00
6123048426 Names & SVG 2024-04-08 21:24:20 +02:00
ddef61a0cf Reassign all mappings to chosen group when disabling groups 2024-04-08 17:44:49 +02:00
59a72e0544 Port regional assignments to parent country if turned off 2024-04-08 13:41:35 +02:00
a3f81c95a0 Add Antarctica SVG 2024-04-08 11:36:05 +02:00
d041df9805 Adapt settings and icons 2024-04-08 11:35:51 +02:00
01dab6aa30 Prevent overriding default group 2024-04-08 10:52:08 +02:00
bafd3cea14 Remove magic group keys 2024-04-08 10:45:16 +02:00
ec52574ae3 Update checkboxes immediately 2024-04-08 10:42:16 +02:00
923404ebc5 Fix regional UI 2024-04-08 00:42:35 +02:00
32ba5e0b07 Merge Shetland Islands with Scotland 2024-04-07 23:27:12 +02:00
72b2148e4b Change some country names 2024-04-07 22:21:08 +02:00
513660b3a4 Reorganize countries in 'Others' group 2024-04-07 22:04:33 +02:00
443d62b6df Fixed state names 2024-04-07 11:59:37 +02:00
a360c7496b Added prerelease to build 2024-04-07 11:25:19 +02:00
3fe83cff2e Fix debug build if no key 2024-04-07 11:10:27 +02:00
71acf04f20 Lock file maintenance 2024-04-06 00:04:23 +00:00
b1de332134 [m] Keystore def 2024-04-04 00:36:54 +02:00
112745188f [m] Fix name 2024-04-04 00:30:18 +02:00
65 changed files with 22796 additions and 8759 deletions

View File

@ -48,17 +48,17 @@ jobs:
cache: 'gradle'
- name: Build APK
run: ./gradlew assemble
# - name: Upload APK
# uses: actions/upload-artifact@v4
# with:
# name: app.apk
# path: app/build/outputs/apk/release/app-release.apk
run: ./gradlew assembleSignedRelease
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
app/build/outputs/apk/release/app-release.apk
app/build/outputs/apk/signedRelease/app-signedRelease.apk
prerelease: |
if [[ ${{ github.ref }} =~ ^refs/tags/[0-9]+\.[0-9]+[a-z]+$ ]]; then
echo "false"
else
echo "true"
fi

View File

@ -2,9 +2,10 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.23'
id 'com.mikepenz.aboutlibraries.plugin' version '11.1.1'
id 'com.mikepenz.aboutlibraries.plugin' version '11.1.3'
}
android {
namespace 'net.helcel.beans'
compileSdk 34
@ -16,22 +17,37 @@ android {
versionCode 1
versionName "0.1a"
}
signingConfigs {
create("release") {
try {
def keystorePropertiesFile = rootProject.file("app/keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
} catch (FileNotFoundException e) {
println("File not found: ${e.message}")
}
}
}
buildTypes {
debug {
debuggable true
}
release {
minifyEnabled true
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
signedRelease {
minifyEnabled true
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig = signingConfigs.getByName("release")
}
}
@ -71,6 +87,5 @@ dependencies {
implementation 'com.caverock:androidsvg-aar:1.4'
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation "com.github.AppDevNext:AndroidChart:3.1.0.21"
implementation 'com.mikepenz:aboutlibraries:11.1.1'
implementation 'com.mikepenz:aboutlibraries:11.1.3'
}

View File

@ -3,18 +3,18 @@
xmlns:tools="http://schemas.android.com/tools">
<application
android:hardwareAccelerated="false"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:hardwareAccelerated="false"
android:icon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Beans"
tools:targetApi="31"
tools:replace="android:allowBackup"
>
tools:targetApi="31">
<profileable android:shell="true" />
<activity
android:name=".activity.MainActivity"
android:exported="true">
@ -31,7 +31,7 @@
</intent-filter>
</activity>
<activity
android:name=".activity.StatActivity"
android:name=".activity.StatsActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 MiB

View File

@ -32,7 +32,8 @@ AFG_TK|AFG|Takhar|12361
AFG_OZ|AFG|Uruzgan|12900
AFG_VR|AFG|Wardak|8945
AFG_ZB|AFG|Zabul|17375
XAD_NA|XAD|Dhekelia|125
XAD_Akrotiri|XAD|Akrotiri|109
XAD_Dhekelia|XAD|Dhekelia|125
ALA_AR|ALA|Archipelago|448
ALA_CO|ALA|Countryside|1022
ALA_MH|ALA|Mariehamn|13
@ -126,14 +127,17 @@ AGO_NA|AGO|Namibe|58240
AGO_UI|AGO|Uíge|62425
AGO_ZA|AGO|Zaire|36821
AIA_BP|AIA|Blowing Point|5
AIA_NA|AIA|Sombrero Island|0
AIA_DogIsland|AIA|Dog Island|2
AIA_EE|AIA|East End|5
AIA_GH|AIA|George Hill|7
AIA_IH|AIA|Island Harbour|6
AIA_NH|AIA|North Hill|1
AIA_NS|AIA|North Side|9
AIA_PriclyPearCays|AIA|Pricly Pear Cays|0
AIA_SG|AIA|Sandy Ground|1
AIA_SH|AIA|Sandy Hill|7
AIA_ScrubIsland|AIA|Scrub Island|4
AIA_SombreroIsland|AIA|Sombrero Island|0
AIA_SO|AIA|South Hill|7
AIA_ST|AIA|Stoney Ground|7
AIA_TF|AIA|The Farrington|5
@ -203,8 +207,16 @@ AUT_ST|AUT|Steiermark|16408
AUT_TR|AUT|Tirol|12646
AUT_VO|AUT|Vorarlberg|2602
AUT_WI|AUT|Wien|415
AZE_NA|AZE|Yukhari-Karabakh|7407
AZE_Absheron|AZE|Absheron|6147
AZE_Aran|AZE|Aran|21914
AZE_Daglig-Shirvan|AZE|Daglig-Shirvan|5989
AZE_Ganja-Qazakh|AZE|Ganja-Qazakh|12044
AZE_Kalbajar-Lachin|AZE|Kalbajar-Lachin|5770
AZE_LA|AZE|Lankaran|5592
AZE_Nakhchivan|AZE|Nakhchivan|5400
AZE_Quba-Khachmaz|AZE|Quba-Khachmaz|7339
AZE_Shaki-Zaqatala|AZE|Shaki-Zaqatala|8729
AZE_Yukhari-Karabakh|AZE|Yukhari-Karabakh|7407
BHS_AK|BHS|Acklins|496
BHS_BR|BHS|Berry Islands|61
BHS_BI|BHS|Biminis|34
@ -266,7 +278,9 @@ BLR_HR|BLR|Grodno|24952
BLR_MI|BLR|Minsk|2255
BLR_MA|BLR|Mogilev|28984
BLR_VI|BLR|Vitebsk|40056
BEL_NA|BEL|Wallonie|16827
BEL_Bruxelles|BEL|Bruxelles|156
BEL_Vlaanderen|BEL|Vlaanderen|13685
BEL_Wallonie|BEL|Wallonie|16827
BLZ_BZ|BLZ|Belize|3372
BLZ_CY|BLZ|Cayo|5322
BLZ_CZ|BLZ|Corozal|2012
@ -374,7 +388,11 @@ BRA_SC|BRA|Santa Catarina|96032
BRA_SP|BRA|São Paulo|249417
BRA_SE|BRA|Sergipe|22079
BRA_TO|BRA|Tocantins|279170
VGB_NA|VGB|Virgin Gorda|28
VGB_Anegada|VGB|Anegada|40
VGB_JostVanDyke|VGB|Jost Van Dyke|11
VGB_OtherIslands|VGB|Other Islands|14
VGB_Tortola|VGB|Tortola|76
VGB_VirginGorda|VGB|Virgin Gorda|28
BRN_BE|BRN|Belait|2863
BRN_BM|BRN|Brunei and Muara|533
BRN_TE|BRN|Temburong|1283
@ -636,7 +654,17 @@ COL_VD|COL|Vichada|100014
COM_MO|COM|Mwali|220
COM_GC|COM|Njazídja|1028
COM_AN|COM|Nzwani|436
COK_NA|COK|Rarotonga|70
COK_Aitutaki|COK|Aitutaki|28
COK_Atiu|COK|Atiu|31
COK_Mangaia|COK|Mangaia|49
COK_Manihiki|COK|Manihiki|8
COK_Mauke|COK|Mauke|20
COK_Mitiaro|COK|Mitiaro|25
COK_Palmerston|COK|Palmerston|24
COK_Penhryn|COK|Penhryn|17
COK_Pukapuka|COK|Pukapuka|6
COK_Rakahanga|COK|Rakahanga|5
COK_Rarotonga|COK|Rarotonga|70
CRI_AL|CRI|Alajuela|9834
CRI_CA|CRI|Cartago|3113
CRI_GU|CRI|Guanacaste|10250
@ -878,7 +906,7 @@ EST_JN|EST|Jõgeva|2597
EST_LN|EST|Lääne|2420
EST_LV|EST|Lääne-Viru|3478
EST_PR|EST|Pärnu|4796
EST_NA|EST|Peipsi|1758
EST_Peipsi|EST|Peipsi|1758
EST_PL|EST|Põlva|2161
EST_RA|EST|Rapla|2971
EST_SA|EST|Saare|2932
@ -934,7 +962,7 @@ PYF_MI|PYF|Îles Marquises|996
PYF_LI|PYF|Îles Sous-le-Vent|429
PYF_TG|PYF|Îles Tuamotu-Gambier|1039
ATF_CR|ATF|Îles Crozet|372
ATF_NA|ATF|ÎlesÉparses|44
ATF_ÎlesÉparses|ATF|Îles Éparses|44
ATF_AS|ATF|Îles Saint Paulet Amsterdam|64
ATF_KG|ATF|Kerguelen|7372
GAB_ES|GAB|Estuaire|20024
@ -1071,9 +1099,14 @@ GGY_SV|GGY|Saint Saviour|6
GGY_SK|GGY|Sark|7
GGY_TV|GGY|Torteval|3
GGY_VA|GGY|Vale|10
GIN_NA|GIN|Nzérékoré|36751
GIN_Boké|GIN|Boké|34287
GIN_C|GIN|Conakry|423
GIN_Faranah|GIN|Faranah|35989
GIN_K|GIN|Kankan|72197
GIN_Kindia|GIN|Kindia|25816
GIN_Labé|GIN|Labé|22959
GIN_Mamou|GIN|Mamou|17935
GIN_Nzérékoré|GIN|Nzérékoré|36751
GNB_BA|GNB|Bafatá|5881
GNB_BM|GNB|Biombo|761
GNB_BS|GNB|Bissau|83
@ -1298,7 +1331,7 @@ IMN_MC|IMN|Michael|34
IMN_MD|IMN|Santon|16
IMN_GR|IMN|Garff|72
IMN_GB|IMN|Peel|2
ISR_NA|ISR|Golan|1238
ISR_Golan|ISR|Golan|1238
ISR_HD|ISR|Ha Darom|14557
ISR_HA|ISR|Haifa|887
ISR_HM|ISR|Ha Merkaz|1243
@ -1471,10 +1504,13 @@ KEN_UG|KEN|Uasin Gishu|3453
KEN_VI|KEN|Vihiga|562
KEN_WJ|KEN|Wajir|57017
KEN_WP|KEN|West Pokot|9574
XKO_NA|XKO|Uroševac|1056
XKO_Đakovica|XKO|Đakovica|1109
XKO_Gnjilane|XKO|Gnjilane|1360
XKO_KM|XKO|Kosovska Mitrovica|2070
XKO_PE|XKO|Pećki|1357
XKO_Pristina|XKO|Pristina|2175
XKO_PZ|XKO|Prizren|1715
XKO_Uroševac|XKO|Uroševac|1056
KWT_AH|KWT|Al Ahmadi|4659
KWT_FA|KWT|Al Farwaniyah|219
KWT_JA|KWT|Al Jahrah|12438
@ -1512,7 +1548,14 @@ LVA_L|LVA|Latgale|14678
LVA_R|LVA|Riga|10324
LVA_V|LVA|Vidzeme|15240
LVA_Z|LVA|Zemgale|10775
LBN_NA|LBN|South|919
LBN_Akkar|LBN|Akkar|793
LBN_Baalbak-Hermel|LBN|Baalbak-Hermel|2854
LBN_Beirut|LBN|Beirut|21
LBN_Bekaa|LBN|Bekaa|1408
LBN_MountLebanon|LBN|Mount Lebanon|1990
LBN_Nabatiyeh|LBN|Nabatiyeh|1099
LBN_North|LBN|North|1181
LBN_South|LBN|South|919
LSO_BE|LSO|Berea|1999
LSO_BB|LSO|Butha-Buthe|1796
LSO_LE|LSO|Leribe|2829
@ -1624,7 +1667,7 @@ MKD_KZ|MKD|Kriva Palanka|508
MKD_KG|MKD|Krivogaštani|95
MKD_KS|MKD|Kruševo|183
MKD_UM|MKD|Kumanovo|503
MKD_NA|MKD|Staro Nagoričane|438
MKD_LakeOhrid|MKD|Lake Ohrid|247
MKD_LI|MKD|Lipkovo|265
MKD_LO|MKD|Lozovo|161
MKD_MK|MKD|Makedonska Kamenica|198
@ -1647,6 +1690,7 @@ MKD_RM|MKD|Rosoman|133
MKD_AJ|MKD|Saraj|234
MKD_SS|MKD|Sopište|214
MKD_SD|MKD|Star Dojran|150
MKD_NA|MKD|Staro Nagoričane|438
MKD_ST|MKD|Štip|565
MKD_UG|MKD|Struga|475
MKD_RU|MKD|Strumitsa|320
@ -1669,7 +1713,7 @@ MDG_D|MDG|Antsiranana|44120
MDG_F|MDG|Fianarantsoa|101276
MDG_M|MDG|Mahajanga|152526
MDG_A|MDG|Toamasina|71636
MDG_NA|MDG|Toliary|164809
MDG_Toliary|MDG|Toliary|164809
MWI_BA|MWI|Balaka|2143
MWI_BL|MWI|Blantyre|2038
MWI_CK|MWI|Chikwawa|4908
@ -1728,9 +1772,29 @@ MLT_GO|MLT|Għawdex|71
MLT_SO|MLT|Nofsinhar|78
MLT_NO|MLT|Tramuntana|116
MLT_SE|MLT|Xlokk|36
MHL_NA|MHL|NA|26
MHL_Ailinglaplap|MHL|Ailinglaplap|18
MHL_Ailuk|MHL|Ailuk|11
MHL_Arno|MHL|Arno|28
MHL_Aur|MHL|Aur|6
MHL_Ebon|MHL|Ebon|8
MHL_Enewetok|MHL|Enewetok|16
MHL_Jabat|MHL|Jabat|1
MHL_Jaluit|MHL|Jaluit|13
MHL_KWA|MHL|Kwajalein|27
MHL_Lae|MHL|Lae|3
MHL_Lib|MHL|Lib|1
MHL_Likiep|MHL|Likiep|13
MHL_MAJ|MHL|Majuro|22
MHL_Maloelap|MHL|Maloelap|12
MHL_Mejit|MHL|Mejit|4
MHL_Mili|MHL|Mili|27
MHL_Namorik|MHL|Namorik|5
MHL_Namu|MHL|Namu|7
MHL_Ujae|MHL|Ujae|3
MHL_Utirik|MHL|Utirik|14
MHL_Wotho|MHL|Wotho|6
MHL_Wotje|MHL|Wotje|15
MHL_19_1|MHL|NA|26
MTQ_FF|MTQ|Fort-de-France|189
MTQ_MA|MTQ|Le Marin|393
MTQ_TR|MTQ|Le Trinité|353
@ -1896,7 +1960,7 @@ MAR_FB|MAR|Fès-Boulemane|19366
MAR_GB|MAR|Gharb-Chrarda-Béni Hssen|8782
MAR_GC|MAR|Grand Casablanca|879
MAR_GE|MAR|Guelmim-Es-Semara|64701
MAR_LB|MAR|Laâyoune-Boujdour-Sakia El H|5763
MAR_LB|MAR|Laâyoune-Boujdour-Sakia El Hamra|5763
MAR_MK|MAR|Marrakech-Tensift-Al Haouz|32483
MAR_MT|MAR|Meknès-Tafilalet|60303
MAR_OR|MAR|Oriental|59914
@ -1968,13 +2032,15 @@ NLD_FL|NLD|Flevoland|1466
NLD_FR|NLD|Fryslân|3573
NLD_GE|NLD|Gelderland|5102
NLD_GR|NLD|Groningen|2370
NLD_SH|NLD|Zuid-Holland|3143
NLD_IJsselmeer|NLD|IJsselmeer|1995
NLD_LI|NLD|Limburg|2159
NLD_NB|NLD|Noord-Brabant|5082
NLD_NH|NLD|Noord-Holland|2872
NLD_OV|NLD|Overijssel|3369
NLD_UT|NLD|Utrecht|1555
NLD_ZE|NLD|Zeeland|1804
NLD_Zeeuwsemeren|NLD|Zeeuwsemeren|477
NLD_14_1|NLD|NA|3143
NCL_IL|NCL|Îles Loyauté|1988
NCL_NO|NCL|Nord|9520
NCL_SU|NCL|Sud|7408
@ -2067,13 +2133,18 @@ PRK_WB|PRK|Hwanghae-bukto|8248
PRK_WN|PRK|Hwanghae-namdo|8563
PRK_KS|PRK|Kaesŏng|1182
PRK_KW|PRK|Kangwŏn-do|10286
PRK_NA|PRK|Sinŭiju|109
PRK_Kumgangsan|PRK|Kumgangsan|987
PRK_PB|PRK|P'yŏngan-bukto|12424
PRK_PN|PRK|P'yŏngan-namdo|12479
PRK_PY|PRK|P'yŏngyang|2718
PRK_NJ|PRK|Rasŏn|856
PRK_YG|PRK|Ryanggang|13935
ZNC_NA|ZNC|Nicosia|522
PRK_Sinŭiju|PRK|Sinŭiju|109
ZNC_Gazimağusa|ZNC|Gazimağusa|927
ZNC_Girne|ZNC|Girne|677
ZNC_Güzelyurt|ZNC|Güzelyurt|346
ZNC_Iskele|ZNC|Iskele|849
ZNC_Nicosia|ZNC|Nicosia|522
MNP_NI|MNP|Northern Islands|181
MNP_RO|MNP|Rota|90
MNP_SA|MNP|Saipan|123
@ -2318,7 +2389,7 @@ PRT_FA|PRT|Faro|4975
PRT_GU|PRT|Guarda|5541
PRT_LE|PRT|Leiria|3501
PRT_LI|PRT|Lisboa|2765
PRT_NA|PRT|Madeira|801
PRT_Madeira|PRT|Madeira|801
PRT_PA|PRT|Portalegre|6091
PRT_PO|PRT|Porto|2332
PRT_SA|PRT|Santarém|6725
@ -2511,7 +2582,7 @@ RUS_LP|RUS|Lipetsk|24425
RUS_MG|RUS|Magadan|459480
RUS_ME|RUS|Mariy-El|23468
RUS_MR|RUS|Mordovia|26161
RUS_NA|RUS|Moscow City|1095
RUS_MoscowCity|RUS|Moscow City|1095
RUS_MS|RUS|Moskva|46592
RUS_MM|RUS|Murmansk|142851
RUS_NN|RUS|Nenets|175502
@ -2557,7 +2628,8 @@ RWA_SU|RWA|Amajyepfo|5997
RWA_ES|RWA|Iburasirazuba|9530
RWA_OU|RWA|Iburengerazuba|5910
RWA_KV|RWA|Umujyiwa Kigali|733
BLM_NA|BLM|Sousle Vent|8
BLM_AuVent|BLM|Au Vent|13
BLM_SousleVent|BLM|Sous le Vent|8
SHN_AC|SHN|Ascension|100
SHN_SH|SHN|Saint Helena|124
SHN_TA|SHN|Tristanda Cunha|189
@ -2697,7 +2769,11 @@ SLE_EA|SLE|Eastern|15846
SLE_NO|SLE|Northern|36238
SLE_SO|SLE|Southern|20261
SLE_WE|SLE|Western|722
SGP_NA|SGP|West|230
SGP_Central|SGP|Central|133
SGP_East|SGP|East|103
SGP_North|SGP|North|131
SGP_North-East|SGP|North-East|103
SGP_West|SGP|West|230
SVK_BC|SVK|Banskobystrický|9565
SVK_BL|SVK|Bratislavský|2015
SVK_KI|SVK|Košický|6768
@ -2708,7 +2784,7 @@ SVK_TA|SVK|Trnavský|4125
SVK_ZI|SVK|Žilinský|6828
SVN_GO|SVN|Gorenjska|2117
SVN_SP|SVN|Goriška|2277
SVN_NA|SVN|Jugovzhodna Slovenija|2635
SVN_JugovzhodnaSlovenija|SVN|Jugovzhodna Slovenija|2635
SVN_KO|SVN|Koroška|1032
SVN_NO|SVN|Notranjsko-kraška|1452
SVN_JP|SVN|Obalno-kraška|945
@ -3191,7 +3267,12 @@ TKM_BA|TKM|Balkan|136605
TKM_DA|TKM|Daşoguz|76751
TKM_LE|TKM|Lebap|96478
TKM_MA|TKM|Mary|86353
TCA_NA|TCA|South Caicosand East Caicos|247
TCA_GrandTurk|TCA|Grand Turk|20
TCA_MiddleCaicos|TCA|Middle Caicos|306
TCA_NorthCaicos|TCA|North Caicos|259
TCA_ProvidencialesandWestCaicos|TCA|Providenciales and West Caicos|152
TCA_SaltCay|TCA|Salt Cay|11
TCA_SouthCaicosandEastCaicos|TCA|South Caicos and East Caicos|247
TUV_FN|TUV|Funafuti|7
TUV_NG|TUV|Nanumanga|3
TUV_NA|TUV|Nanumea|4
@ -3231,7 +3312,8 @@ UGA_TG|UGA|Kitgum|9621
UGA_KF|UGA|Kotido|13366
UGA_KU|UGA|Kumi|2867
UGA_KJ|UGA|Kyenjojo|4125
UGA_NA|UGA|Nakasongola|3536
UGA_LakeAlbert|UGA|Lake Albert|3212
UGA_LakeVictoria|UGA|Lake Victoria|28585
UGA_LA|UGA|Lira|7285
UGA_LW|UGA|Luwero|5734
UGA_MA|UGA|Masaka|3643
@ -3245,6 +3327,7 @@ UGA_MI|UGA|Mpigi|3321
UGA_MD|UGA|Mubende|6242
UGA_MN|UGA|Mukono|3434
UGA_NP|UGA|Nakapiripirit|5859
UGA_NA|UGA|Nakasongola|3536
UGA_NE|UGA|Nebbi|2910
UGA_NT|UGA|Ntungamo|2068
UGA_PD|UGA|Pader|6905
@ -3295,7 +3378,7 @@ ARE_UQ|ARE|Ummal-Qaywayn|746
GBR_NIR|GBR|Northern Ireland|14134
GBR_SCT|GBR|Scotland|78704
GBR_WLS|GBR|Wales|20818
GBR_NA|GBR|NA|130659
GBR_1_1|GBR|England|130659
USA_AL|USA|Alabama|133995
USA_AK|USA|Alaska|1501231
USA_AZ|USA|Arizona|296082
@ -3347,7 +3430,15 @@ USA_WA|USA|Washington|174789
USA_WV|USA|West Virginia|62782
USA_WI|USA|Wisconsin|169315
USA_WY|USA|Wyoming|253420
UMI_NA|UMI|Wake|9
UMI_Baker|UMI|Baker|2
UMI_Howland|UMI|Howland|2
UMI_Jarvisisland|UMI|Jarvis island|5
UMI_Johnston|UMI|Johnston|5
UMI_KingmanReef|UMI|Kingman Reef|3
UMI_Midway|UMI|Midway|12
UMI_Navassa|UMI|Navassa|5
UMI_Palmyra|UMI|Palmyra|4
UMI_Wake|UMI|Wake|9
URY_AR|URY|Artigas|12058
URY_CA|URY|Canelones|4536
URY_CL|URY|Cerro Largo|13843
@ -3388,22 +3479,28 @@ VUT_SE|VUT|Shefa|1522
VUT_TF|VUT|Tafea|1666
VUT_TR|VUT|Torba|889
VEN_Z|VEN|Amazonas|184052
VEN_NA|VEN|Vargas|1002
VEN_Anzoátegui|VEN|Anzoátegui|48025
VEN_C|VEN|Apure|74003
VEN_D|VEN|Aragua|6977
VEN_E|VEN|Barinas|36436
VEN_Bolívar|VEN|Bolívar|241518
VEN_G|VEN|Carabobo|4812
VEN_H|VEN|Cojedes|14572
VEN_Y|VEN|Delta Amacuro|40278
VEN_DP|VEN|Dependencias Federales|343
VEN_A|VEN|Distrito Capital|329
VEN_Falcón|VEN|Falcón|27275
VEN_Guárico|VEN|Guárico|67685
VEN_K|VEN|Lara|19166
VEN_Mérida|VEN|Mérida|12914
VEN_M|VEN|Miranda|8623
VEN_N|VEN|Monagas|29251
VEN_O|VEN|Nueva Esparta|1039
VEN_P|VEN|Portuguesa|19622
VEN_R|VEN|Sucre|10950
VEN_Táchira|VEN|Táchira|10851
VEN_T|VEN|Trujillo|8129
VEN_Vargas|VEN|Vargas|1002
VEN_U|VEN|Yaracuy|6259
VEN_V|VEN|Zulia|44191
VNM_AG|VNM|An Giang|3547
@ -3532,4 +3629,3 @@ Z05_UT|IND|Uttarakhand|259
Z09_UT|IND|Uttarakhand|987
Z06_JK|PAK|Azad Kashmir|13931
Z06_NA|PAK|Gilgit-Baltistan|68053
GBR_EN|GBR|England|417

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.5 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

@ -1,15 +1,22 @@
package net.helcel.beans.activity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.google.android.material.tabs.TabLayoutMediator
import net.helcel.beans.R
import net.helcel.beans.activity.adapter.ViewPagerAdapter
import net.helcel.beans.activity.fragment.EditGroupAddFragment
import net.helcel.beans.activity.fragment.EditPlaceColorFragment
import net.helcel.beans.activity.fragment.EditPlaceFragment
import net.helcel.beans.countries.World
import net.helcel.beans.databinding.ActivityEditBinding
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.DialogCloser
import net.helcel.beans.helper.Settings
import net.helcel.beans.helper.Theme.createActionBar
@ -39,8 +46,24 @@ class EditActivity : AppCompatActivity() {
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
if (Settings.isSingleGroup(this)) {
menuInflater.inflate(R.menu.menu_edit, menu)
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
finish()
when (item.itemId) {
R.id.action_color -> {
Data.groups.getUniqueEntry()?.let { group ->
EditGroupAddFragment(group.key, {
(_binding.pager.adapter as ViewPagerAdapter?)?.refreshColors(group.color)
}, {}, false).show(supportFragmentManager, "AddColorDialogFragment")
}
}
else -> finish()
}
return super.onOptionsItemSelected(item)
}

View File

@ -24,6 +24,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var css: CSSWrapper
override fun onRestart() {
refreshProjection()
refreshMap()
super.onRestart()
}
@ -36,7 +37,7 @@ class MainActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val d = when (item.itemId) {
R.id.action_edit -> EditActivity::class.java
R.id.action_stats -> StatActivity::class.java
R.id.action_stats -> StatsActivity::class.java
R.id.action_settings -> SettingsActivity::class.java
else -> throw Exception("Non Existent Menu Item")
}
@ -50,7 +51,6 @@ class MainActivity : AppCompatActivity() {
Settings.start(this)
supportActionBar?.setBackgroundDrawable(colorWrapper(this, android.R.attr.colorPrimary))
setContentView(_binding.root)
_binding.photoView.minimumScale = 1f
@ -58,9 +58,8 @@ class MainActivity : AppCompatActivity() {
GeoLocImporter.importStates(this)
Data.loadData(this, Int.MIN_VALUE)
psvg = SVGWrapper(this)
css = CSSWrapper(this)
refreshProjection()
refreshMap()
}
@ -70,4 +69,9 @@ class MainActivity : AppCompatActivity() {
_binding.photoView.setImageDrawable(PictureDrawable(psvg.get()?.renderToPicture(opt)))
}
fun refreshProjection() {
psvg = SVGWrapper(this)
css = CSSWrapper(this)
}
}

View File

@ -1,104 +0,0 @@
package net.helcel.beans.activity
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
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.github.mikephil.charting.utils.MPPointF
import net.helcel.beans.R
import net.helcel.beans.countries.World
import net.helcel.beans.helper.Data.groups
import net.helcel.beans.helper.Data.visits
import net.helcel.beans.helper.Theme.colorWrapper
import net.helcel.beans.helper.Theme.createActionBar
class StatActivity : AppCompatActivity() {
private lateinit var chart: PieChart
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_stat)
createActionBar(this, getString(R.string.action_stat))
chart = findViewById(R.id.chart)
chart.setUsePercentValues(true)
chart.description.isEnabled = false
chart.setExtraOffsets(5F, 10F, 5F, 5F)
chart.centerText = "Country Area"
chart.setDrawCenterText(true)
chart.isDrawHoleEnabled = true
chart.setTransparentCircleColor(Color.TRANSPARENT)
chart.setHoleColor(Color.TRANSPARENT)
chart.setCenterTextColor(colorWrapper(this, android.R.attr.colorForeground).color)
chart.setTransparentCircleAlpha(0)
chart.holeRadius = 40F
chart.transparentCircleRadius = 40F
chart.rotationAngle = 0F
chart.isRotationEnabled = false
chart.isHighlightPerTapEnabled = false
chart.legend.isEnabled = false
bind()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
finish()
return super.onOptionsItemSelected(item)
}
private fun bind() {
val entries = ArrayList<PieEntry>()
val VIS_continents = World.WWW.children.groupBy { visits.getVisited(it) }
.map { Pair(it.key, it.value.map { c -> c.area }.fold(0) { acc, i -> acc + i }) }
val VIS_country =
World.WWW.children.map { it.children }.flatten().groupBy { visits.getVisited(it) }
.map { Pair(it.key, it.value.map { c -> c.area }.fold(0) { acc, i -> acc + i }) }
val vis = VIS_country
Log.d("VIS", vis.toString())
val max = vis.map { it.second }.fold(0) { acc, i -> acc + i }
vis.forEach {
entries.add(
PieEntry(
it.second.toFloat().div(max.toFloat()),
groups.getGroupFromKey(it.first).name
)
)
}
val dataSet = PieDataSet(entries, "GG1")
dataSet.valueTextColor = Color.BLACK
dataSet.sliceSpace = 3f
dataSet.iconsOffset = MPPointF(0f, 40f)
dataSet.selectionShift = 5f
dataSet.setDrawIcons(true)
dataSet.colors = vis.map { groups.getGroupFromKey(it.first).color.color }.toList()
val data = PieData(dataSet)
data.setDrawValues(false)
data.setValueFormatter(PercentFormatter())
data.setValueTextSize(11f)
data.setValueTextColor(Color.BLACK)
chart.setEntryLabelColor(Color.BLACK)
chart.data = data
chart.highlightValues(null)
chart.invalidate()
}
}

View File

@ -0,0 +1,56 @@
package net.helcel.beans.activity
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayoutMediator
import net.helcel.beans.R
import net.helcel.beans.activity.adapter.StatsListAdapter
import net.helcel.beans.countries.GeoLoc.LocType
import net.helcel.beans.databinding.ActivityStatBinding
import net.helcel.beans.helper.Settings
import net.helcel.beans.helper.Theme.createActionBar
private val MODE_LIST = listOf(LocType.WORLD, LocType.COUNTRY, LocType.STATE)
class StatsActivity : AppCompatActivity() {
private lateinit var _binding: ActivityStatBinding
private var activeMode = LocType.WORLD
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityStatBinding.inflate(layoutInflater)
setContentView(_binding.root)
createActionBar(this, getString(R.string.action_stat))
_binding.stats.layoutManager =
LinearLayoutManager(this, RecyclerView.VERTICAL, false)
val adapter = StatsListAdapter(_binding.stats, _binding.name)
_binding.stats.adapter = adapter
_binding.pager.adapter = object : FragmentStateAdapter(supportFragmentManager, lifecycle) {
override fun getItemCount(): Int = if (Settings.isRegional(applicationContext)) 3 else 2
override fun createFragment(position: Int): Fragment = Fragment()
}
TabLayoutMediator(_binding.tab, _binding.pager) { tab, position ->
tab.text = MODE_LIST[position].txt
}.attach()
_binding.pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
activeMode = MODE_LIST[position]
adapter.refreshMode(activeMode)
}
})
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
finish()
return super.onOptionsItemSelected(item)
}
}

View File

@ -3,39 +3,44 @@ package net.helcel.beans.activity.adapter
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.checkbox.MaterialCheckBox
import net.helcel.beans.R
import net.helcel.beans.activity.fragment.EditPlaceColorFragment
import net.helcel.beans.activity.fragment.EditPlaceFragment
import net.helcel.beans.countries.GeoLoc
import net.helcel.beans.databinding.ItemListGeolocBinding
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.Settings
import net.helcel.beans.helper.*
import net.helcel.beans.helper.Theme.colorWrapper
class GeolocListAdapter(
private val ctx: EditPlaceFragment, private val l: GeoLoc, private val pager: ViewPagerAdapter
private val ctx: EditPlaceFragment, private val l: GeoLoc, private val pager: ViewPagerAdapter,
private val parentHolder: FoldingListViewHolder?
) : RecyclerView.Adapter<GeolocListAdapter.FoldingListViewHolder>() {
private val sortedList = l.children.toList().sortedBy { it.fullName }
private val holders: MutableSet<FoldingListViewHolder> = mutableSetOf()
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): FoldingListViewHolder {
val binding = ItemListGeolocBinding.inflate(
LayoutInflater.from(viewGroup.context),
viewGroup,
false
)
return FoldingListViewHolder(ctx.requireActivity(), binding)
val holder = FoldingListViewHolder(ctx.requireActivity(), binding, parentHolder, l)
holders.add(holder)
return holder
}
override fun onBindViewHolder(holder: FoldingListViewHolder, position: Int) {
val el = l.children[position]
val el = sortedList[position]
holder.bind(el)
holder.addListeners(el) {
if (el.children.isNotEmpty())
pager.addFragment(ctx, EditPlaceFragment(el, pager))
pager.addFragment(ctx, EditPlaceFragment(el, pager, holder))
true
}
}
@ -44,23 +49,20 @@ class GeolocListAdapter(
return l.children.size
}
fun refreshColors(colorDrawable: ColorDrawable) {
holders.forEach { it.refreshColor(colorDrawable) }
}
class FoldingListViewHolder(
private val ctx: FragmentActivity,
private val _binding: ItemListGeolocBinding
) : RecyclerView.ViewHolder(_binding.root) {
private val _binding: ItemListGeolocBinding,
private val _parentHolder: FoldingListViewHolder? = null,
private val _parentGeoLoc: GeoLoc,
) : RecyclerView.ViewHolder(_binding.root), DialogCloser {
private lateinit var el: GeoLoc
private fun bindGroup(el: GeoLoc) {
val numerator = el.children.map { Data.visits.getVisited(it) != 0 }.count { it }
val denominator = el.children.size
_binding.count.text = when (Settings.getStatPref(ctx)) {
ctx.getString(R.string.percentages) -> ctx.getString(
R.string.percentage,
(100 * (numerator.toFloat() / denominator.toFloat())).toInt()
)
else -> ctx.getString(R.string.rate, numerator, denominator)
}
refreshCount(el)
_binding.textView.setTypeface(null, Typeface.BOLD)
_binding.textView.backgroundTintList = ColorStateList.valueOf(
colorWrapper(
@ -71,18 +73,27 @@ class GeolocListAdapter(
}
fun bind(el: GeoLoc) {
this.el = el
_binding.textView.text = el.fullName
_binding.textView.backgroundTintList =
ColorStateList.valueOf(colorWrapper(ctx, android.R.attr.colorBackground).color)
if (el.shouldShowChildren(ctx))
if (el.children.isNotEmpty())
bindGroup(el)
refreshCheck(el)
}
fun refreshColor(colorDrawable: ColorDrawable) {
if (Data.visits.getVisited(el) !in listOf(NO_GROUP, AUTO_GROUP)) {
_binding.checkBox.buttonTintList =
ColorStateList.valueOf(colorDrawable.color)
refreshCheck(el)
}
}
fun addListeners(el: GeoLoc, expandLambda: () -> Boolean) {
if (el.shouldShowChildren(ctx)) {
if (el.children.isNotEmpty()) {
_binding.textView.setOnClickListener { expandLambda() }
}
_binding.checkBox.setOnClickListener {
@ -91,11 +102,11 @@ class GeolocListAdapter(
if (_binding.checkBox.isChecked) {
// If one has just checked the box (assign unique group)
Data.selected_group = Data.groups.getUniqueEntry()
onColorDialogDismiss(false)
onDialogDismiss(false)
} else {
// If one has just unchecked the box (unassign unique group)
Data.selected_group = null
onColorDialogDismiss(true)
onDialogDismiss(true)
}
} else {
Data.selected_group = null
@ -104,39 +115,79 @@ class GeolocListAdapter(
"AddColorDialogFragment"
)
}
_parentHolder?.refresh(_parentGeoLoc)
}
}
fun onColorDialogDismiss(clear: Boolean) {
override fun onDialogDismiss(clear: Boolean) {
if (clear) {
Data.visits.setVisited(Data.selected_geoloc, 0)
Data.visits.setVisited(Data.selected_geoloc, NO_GROUP)
Data.saveData()
if (_parentGeoLoc.children.all { Data.visits.getVisited(it) == NO_GROUP }) {
Data.clearing_geoloc = _parentGeoLoc
}
}
if (Data.selected_group != null && Data.selected_geoloc != null) {
Data.visits.setVisited(Data.selected_geoloc, Data.selected_group?.key ?: 0)
Data.visits.setVisited(Data.selected_geoloc, Data.selected_group?.key ?: NO_GROUP)
Data.saveData()
}
Data.selected_geoloc?.let { refreshCheck(it) }
Data.selected_geoloc = null
Data.selected_group = null
_parentHolder?.refresh(_parentGeoLoc)
}
private fun refreshCheck(geoLoc: GeoLoc) {
_binding.checkBox.checkedState =
if (Data.visits.getVisited(geoLoc) !in listOf(NO_GROUP, AUTO_GROUP)) {
MaterialCheckBox.STATE_CHECKED
} else if (geoLoc.children.isNotEmpty() &&
geoLoc.children.all {
Data.visits.getVisited(it) !in listOf(NO_GROUP, AUTO_GROUP)
}
) {
Data.visits.setVisited(geoLoc, AUTO_GROUP)
MaterialCheckBox.STATE_CHECKED
} else if (geoLoc.children.isEmpty() && Data.visits.getVisited(geoLoc) == AUTO_GROUP) {
MaterialCheckBox.STATE_CHECKED
} else if (geoLoc.children.any { Data.visits.getVisited(it) != NO_GROUP }) {
Data.visits.setVisited(geoLoc, AUTO_GROUP)
MaterialCheckBox.STATE_INDETERMINATE
} else {
Data.visits.setVisited(geoLoc, NO_GROUP)
if (Data.clearing_geoloc == geoLoc) {
Data.clearing_geoloc = null
}
MaterialCheckBox.STATE_UNCHECKED
}
Data.saveData()
var col = Data.groups.getGroupFromKey(Data.visits.getVisited(geoLoc)).color
if (col.color == Color.TRANSPARENT) {
col = colorWrapper(
ctx,
android.R.attr.panelColorBackground
)
if (Data.visits.getVisited(geoLoc) == AUTO_GROUP) {
col = colorWrapper(ctx, android.R.attr.colorPrimary)
} else if (col.color == Color.TRANSPARENT) {
col = colorWrapper(ctx, android.R.attr.panelColorBackground)
col.alpha = 64
}
_binding.checkBox.checkedState =
if (Data.visits.getVisited(geoLoc) != 0) MaterialCheckBox.STATE_CHECKED
else if (geoLoc.children.any { Data.visits.getVisited(it) != 0 }) MaterialCheckBox.STATE_INDETERMINATE
else MaterialCheckBox.STATE_UNCHECKED
_binding.checkBox.buttonTintList = ColorStateList.valueOf(col.color)
}
private fun refreshCount(geoLoc: GeoLoc) {
val numerator =
geoLoc.children.map { Data.visits.getVisited(it) != NO_GROUP }.count { it }
val denominator = geoLoc.children.size
_binding.count.text = Settings.getStats(ctx, numerator, denominator)
}
private fun refresh(geoLoc: GeoLoc) {
// Refresh
refreshCheck(geoLoc)
refreshCount(geoLoc)
// Recursively refresh parent
_parentHolder?.refresh(_parentGeoLoc)
}
}
}

View File

@ -13,7 +13,8 @@ import net.helcel.beans.helper.Theme.getContrastColor
class GroupListAdapter(
private val activity: FragmentActivity,
private val selectDialog: DialogFragment
private val selectDialog: DialogFragment,
private val delete: Boolean = false
) : RecyclerView.Adapter<GroupListAdapter.GroupViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroupViewHolder {
@ -63,6 +64,7 @@ class GroupListAdapter(
Data.selected_group = entry.second
selectDialog.dismiss()
}
if (!delete) {
_binding.groupColor.setOnLongClickListener {
dialogFragment.show(
activity.supportFragmentManager,
@ -73,3 +75,4 @@ class GroupListAdapter(
}
}
}
}

View File

@ -0,0 +1,146 @@
package net.helcel.beans.activity.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textview.MaterialTextView
import net.helcel.beans.R
import net.helcel.beans.countries.GeoLoc
import net.helcel.beans.countries.GeoLoc.LocType
import net.helcel.beans.countries.World
import net.helcel.beans.databinding.ItemListGroupBinding
import net.helcel.beans.helper.AUTO_GROUP
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.Groups
import net.helcel.beans.helper.Settings
import net.helcel.beans.helper.Theme.getContrastColor
class StatsListAdapter(private val stats: RecyclerView, private val total: MaterialTextView) :
RecyclerView.Adapter<StatsListAdapter.StatsViewHolder>() {
private var locMode = LocType.WORLD
private lateinit var ctx: Context
private var countMode: Boolean = true
private var initialSum: Int = 0
private val wwwTotal: List<GeoLoc> = World.WWW.children.toList()
private val countryTotal: List<GeoLoc> = World.WWW.children.flatMap { it.children }
private val stateTotal: List<GeoLoc> =
World.WWW.children.flatMap { it.children.flatMap { itt -> itt.children } }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatsViewHolder {
ctx = parent.context
val binding =
ItemListGroupBinding.inflate(LayoutInflater.from(ctx), parent, false)
return StatsViewHolder(binding)
}
override fun onBindViewHolder(holder: StatsViewHolder, pos: Int) {
initialSum += if (pos == itemCount - 1) {
holder.bind(
Pair(
AUTO_GROUP,
Groups.Group(AUTO_GROUP, ctx.getString(R.string.uncategorized))
)
)
} else {
holder.bind(Data.groups.getGroupFromPos(pos))
}
total.text = Settings.getStats(ctx, initialSum, getTotal())
}
override fun getItemCount(): Int {
return Data.groups.size() + 1
}
private fun getTotal(): Int {
return if (countMode) {
when (locMode) {
LocType.WORLD -> wwwTotal.size
LocType.COUNTRY -> countryTotal.size
LocType.STATE -> stateTotal.size
else -> 0
}
} else {
when (locMode) {
LocType.WORLD -> wwwTotal.sumOf { it.area }
LocType.COUNTRY -> countryTotal.sumOf { it.area }
LocType.STATE -> stateTotal.sumOf { it.area }
else -> 0
}
}
}
fun refreshMode(mode: LocType) {
val sum = (0 until itemCount).map {
val viewHolder = stats.findViewHolderForAdapterPosition(it) as? StatsViewHolder
viewHolder?.refresh(mode)
}.reduce { acc, i -> acc?.plus((i ?: 0)) }
total.text = Settings.getStats(ctx, sum, getTotal())
}
inner class StatsViewHolder(
private val _binding: ItemListGroupBinding
) : RecyclerView.ViewHolder(_binding.root) {
private lateinit var data: Pair<Int, Groups.Group>
private lateinit var wwwCount: List<GeoLoc>
private lateinit var countryCount: List<GeoLoc>
private lateinit var stateCount: List<GeoLoc>
fun bind(entry: Pair<Int, Groups.Group>): Int {
data = entry
_binding.groupColor.text = entry.second.name
val entryColor = data.second.color.color
val contrastEntryColor = getContrastColor(entryColor)
_binding.groupColor.setBackgroundColor(entryColor)
_binding.groupColor.setTextColor(contrastEntryColor)
_binding.name.setTextColor(contrastEntryColor)
_binding.groupColor.setOnClickListener {
countMode = !countMode
refreshMode(locMode)
}
compute()
return refresh(locMode)
}
private fun compute() {
val visited = Data.visits.getVisitedByValue(data.first)
wwwCount = World.WWW.children.filter { it.code in visited }
countryCount =
World.WWW.children.map { it.children.filter { itt -> itt.code in visited } }
.flatten()
stateCount =
World.WWW.children.map { it.children.map { itt -> itt.children.filter { ittt -> ittt.code in visited } } }
.flatten().flatten()
}
fun refresh(mode: LocType): Int {
locMode = mode
return if (countMode) {
val count = when (locMode) {
LocType.WORLD -> wwwCount.size
LocType.COUNTRY -> countryCount.size
LocType.STATE -> stateCount.size
else -> -1
}
_binding.name.text = count.toString()
count
} else {
val area = when (locMode) {
LocType.WORLD -> wwwCount.sumOf { it.area }
LocType.COUNTRY -> countryCount.sumOf { it.area }
LocType.STATE -> stateCount.sumOf { it.area }
else -> -1
}
_binding.name.text = area.toString()
area
}
}
}
}

View File

@ -1,11 +1,13 @@
package net.helcel.beans.activity.adapter
import android.graphics.drawable.ColorDrawable
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import net.helcel.beans.activity.fragment.EditPlaceFragment
import kotlin.math.max
class ViewPagerAdapter(
fragmentManager: FragmentManager,
@ -17,15 +19,13 @@ class ViewPagerAdapter(
private val fragmentList: MutableList<EditPlaceFragment> = ArrayList()
fun addFragment(src: EditPlaceFragment?, target: EditPlaceFragment) {
if (src != null) {
while (fragmentList.last() != src) {
fragmentList.removeLast()
notifyItemRemoved(fragmentList.size)
val idx = fragmentList.indexOf(src)
viewPager.currentItem = max(0, idx)
if (src != null && idx >= 0) {
fragmentList.subList(idx + 1, fragmentList.size).clear()
}
}
println(src.toString() + " - " + target.toString())
fragmentList.add(target)
notifyItemInserted(fragmentList.size)
notifyItemRangeChanged(max(0, idx), fragmentList.size)
viewPager.currentItem = fragmentList.size - 1
}
@ -52,6 +52,10 @@ class ViewPagerAdapter(
override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}
fun refreshColors(colorDrawable: ColorDrawable) {
fragmentList.forEach{ it.refreshColors(colorDrawable)}
}
}

View File

@ -24,7 +24,8 @@ import net.helcel.beans.helper.Theme.colorToHex6
class EditGroupAddFragment(
private val key: Int = 0,
val onAddCb: (Int) -> Unit,
val onDelCb: (Int) -> Unit
val onDelCb: (Int) -> Unit,
private val deleteEnabled: Boolean = true
) : DialogFragment() {
private lateinit var _binding: FragmentEditGroupsAddBinding
@ -42,7 +43,7 @@ class EditGroupAddFragment(
_binding.colorView.background = ColorDrawable(grp.color.color)
if (key == 0) {
if (key == 0 || !deleteEnabled) {
_binding.btnDelete.visibility = View.INVISIBLE
_binding.btnDelete.isEnabled = false
}
@ -52,8 +53,8 @@ class EditGroupAddFragment(
.setPositiveButton(android.R.string.ok) { _, _ ->
val pos = Data.groups.findGroupPos(key)
// Remove all countries belonging to that group
// Delete the group
Data.visits.deleteVisited(key)
// Delete the group
Data.groups.deleteGroup(key)
Data.saveData()
onDelCb(pos)

View File

@ -3,17 +3,19 @@ package net.helcel.beans.activity.fragment
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import net.helcel.beans.activity.adapter.GeolocListAdapter
import net.helcel.beans.R
import net.helcel.beans.activity.adapter.GroupListAdapter
import net.helcel.beans.databinding.FragmentEditPlacesColorsBinding
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.DialogCloser
class EditPlaceColorFragment(private val parent: GeolocListAdapter.FoldingListViewHolder) :
class EditPlaceColorFragment(private val parent: DialogCloser, private val delete: Boolean = false) :
DialogFragment() {
private lateinit var _binding: FragmentEditPlacesColorsBinding
@ -21,7 +23,8 @@ class EditPlaceColorFragment(private val parent: GeolocListAdapter.FoldingListVi
private var clear: Boolean = false
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = MaterialAlertDialogBuilder(requireContext())
val ctx = requireContext()
val builder = MaterialAlertDialogBuilder(ctx)
_binding = FragmentEditPlacesColorsBinding.inflate(layoutInflater)
_binding.btnAdd.setOnClickListener {
EditGroupAddFragment(0, {
@ -34,16 +37,24 @@ class EditPlaceColorFragment(private val parent: GeolocListAdapter.FoldingListVi
}
val dialog = builder.setView(_binding.root).create()
listAdapt = GroupListAdapter(requireActivity(), this)
listAdapt = GroupListAdapter(requireActivity(), this, delete)
_binding.groupsColor.layoutManager =
LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
LinearLayoutManager(ctx, RecyclerView.VERTICAL, false)
_binding.groupsColor.adapter = listAdapt
if (delete) {
_binding.btnAdd.visibility = View.GONE
_binding.btnClear.text = ctx.getString(R.string.cancel)
_binding.warningText.text = ctx.getString(R.string.select_group)
} else {
_binding.warningText.text = ctx.getString(R.string.edit_group)
}
return dialog
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
parent.onColorDialogDismiss(clear)
parent.onDialogDismiss(clear)
}
}

View File

@ -1,5 +1,6 @@
package net.helcel.beans.activity.fragment
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -8,11 +9,12 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import net.helcel.beans.activity.adapter.GeolocListAdapter
import net.helcel.beans.activity.adapter.GeolocListAdapter.FoldingListViewHolder
import net.helcel.beans.activity.adapter.ViewPagerAdapter
import net.helcel.beans.countries.GeoLoc
import net.helcel.beans.databinding.FragmentEditPlacesBinding
class EditPlaceFragment(val loc: GeoLoc, private val pager: ViewPagerAdapter) : Fragment() {
class EditPlaceFragment(val loc: GeoLoc, private val pager: ViewPagerAdapter, private val holder: FoldingListViewHolder? = null) : Fragment() {
private lateinit var _binding: FragmentEditPlacesBinding
override fun onCreateView(
@ -26,7 +28,11 @@ class EditPlaceFragment(val loc: GeoLoc, private val pager: ViewPagerAdapter) :
_binding.list.setHasFixedSize(true)
_binding.list.layoutManager =
LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
_binding.list.adapter = GeolocListAdapter(this, loc, pager)
_binding.list.adapter = GeolocListAdapter(this, loc, pager, holder)
return _binding.root
}
fun refreshColors(colorDrawable: ColorDrawable) {
(_binding.list.adapter as GeolocListAdapter?)?.refreshColors(colorDrawable)
}
}

View File

@ -5,29 +5,79 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import net.helcel.beans.R
import net.helcel.beans.countries.GeoLocImporter
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.DialogCloser
import net.helcel.beans.helper.Settings
class SettingsFragment : PreferenceFragmentCompat() {
class SettingsFragment : PreferenceFragmentCompat(), DialogCloser {
private var savedInstanceState: Bundle? = null
private var rootKey: String? = null
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
this.savedInstanceState = savedInstanceState
this.rootKey = rootKey
setPreferencesFromResource(R.xml.fragment_settings, rootKey)
val ctx = requireContext()
findPreference<Preference>(getString(R.string.key_regional))?.setOnPreferenceChangeListener { _, key ->
when (key as String) {
ctx.getString(R.string.off) -> GeoLocImporter.clearStates()
ctx.getString(R.string.on) -> GeoLocImporter.importStates(ctx)
else -> GeoLocImporter.clearStates()
}
true
}
// Select Light/Dark/System Mode
findPreference<Preference>(getString(R.string.key_theme))?.setOnPreferenceChangeListener { _, key ->
setTheme(ctx, key as String)
}
// Select map projection
findPreference<Preference>(getString(R.string.key_projection))?.setOnPreferenceChangeListener { _, key ->
Settings.refreshProjection()
}
// Toggle groups
findPreference<Preference>(getString(R.string.key_group))?.setOnPreferenceChangeListener { _, key ->
if (key as String == ctx.getString(R.string.off)) {
val fragment = EditPlaceColorFragment(this, true)
fragment.show(
this.parentFragmentManager,
"AddColorDialogFragment"
)
false
} else {
true
}
}
// Toggle regional geolocs
findPreference<Preference>(getString(R.string.key_regional))?.setOnPreferenceChangeListener { _, key ->
when (key as String) {
ctx.getString(R.string.off) -> {
MaterialAlertDialogBuilder(requireActivity())
.setMessage(R.string.delete_regions)
.setPositiveButton(android.R.string.ok) { _, _ ->
GeoLocImporter.clearStates()
PreferenceManager.getDefaultSharedPreferences(ctx).edit().putString(
ctx.getString(R.string.key_regional),
ctx.getString(R.string.off)
).apply()
refreshPreferences()
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
false
}
ctx.getString(R.string.on) -> {
GeoLocImporter.importStates(ctx, true)
true
}
else -> false
}
}
// Open license fragment
findPreference<Preference>(getString(R.string.licenses))?.setOnPreferenceClickListener {
requireActivity().supportFragmentManager.beginTransaction()
@ -59,4 +109,34 @@ class SettingsFragment : PreferenceFragmentCompat() {
return true
}
}
override fun onDialogDismiss(clear: Boolean) {
// When turning groups off, select one group to keep and reassign everything
Data.selected_group?.let { selectedGroup ->
// Reassign all visited that are not to selectedGroup to selectedGroup
Data.visits.reassignAllVisitedToGroup(selectedGroup.key)
// Delete all groups that are not selectedGroup
Data.groups.deleteAllExcept(selectedGroup.key)
// Save and clear global variables
Data.saveData()
Data.selected_geoloc = null
Data.selected_group = null
// Actually change preference
val ctx = requireContext()
val sp = PreferenceManager.getDefaultSharedPreferences(ctx)
sp.edit().putString(ctx.getString(R.string.key_group), ctx.getString(R.string.off))
.apply()
// Refresh entire preference fragment to reflect changes
refreshPreferences()
}
}
private fun refreshPreferences() {
preferenceScreen.removeAll()
onCreatePreferences(savedInstanceState, rootKey)
}
}

View File

@ -8,8 +8,6 @@ enum class Country(
HKG("Hong Kong", 1104),
MAC("Macao", 32),
ANT("Netherlands Antilles", 800),
AFG("Afghanistan", 645487),
XAD("Akrotiri and Dhekelia", 234),
ALA("Åland", 1483),
@ -217,7 +215,7 @@ enum class Country(
SLB("Solomon Islands", 28686),
SOM("Somalia", 637672),
ZAF("South Africa", 1224059),
SGS("South Georgia and the South Sand", 4085),
SGS("South Georgia and the South Sandwich Islands", 4085),
KOR("South Korea", 100721),
SSD("South Sudan", 632186),
ESP("Spain", 506617),
@ -248,7 +246,7 @@ enum class Country(
ARE("United Arab Emirates", 71429),
GBR("United Kingdom", 244732),
USA("United States", 9477483),
UMI("United States Minor Outlying Isl", 47),
UMI("United States Minor Outlying Islands", 47),
URY("Uruguay", 178103),
UZB("Uzbekistan", 447894),
VUT("Vanuatu", 12384),
@ -265,5 +263,5 @@ enum class Country(
override val code = this.name
override val type = GeoLoc.LocType.COUNTRY
override val children: MutableList<GeoLoc> = ArrayList()
override val children: MutableSet<GeoLoc> = HashSet()
}

View File

@ -1,13 +1,10 @@
package net.helcel.beans.countries
import android.content.Context
import net.helcel.beans.helper.Settings
interface GeoLoc {
enum class LocType {
WORLD, GROUP, CUSTOM_GROUP, COUNTRY, STATE;
enum class LocType(val txt: String) {
WORLD("World"), GROUP("Group"), CUSTOM_GROUP("Group"), COUNTRY("Country"), STATE("State");
}
val code: String
@ -15,16 +12,7 @@ interface GeoLoc {
val area: Int
val type: LocType
val children: List<GeoLoc>
fun shouldShowChildren(ctx: Context): Boolean {
if (children.isEmpty())
return false
if (type == LocType.COUNTRY && !Settings.isRegional(ctx))
return false
return true
}
val children: Set<GeoLoc>
}

View File

@ -1,25 +1,44 @@
package net.helcel.beans.countries
import android.content.Context
import net.helcel.beans.helper.AUTO_GROUP
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.NO_GROUP
import net.helcel.beans.helper.Settings
import java.io.BufferedReader
import java.io.InputStreamReader
object GeoLocImporter {
fun importStates(ctx: Context) {
if (!Settings.isRegional(ctx)) {
fun importStates(ctx: Context, force: Boolean = false) {
if (!Settings.isRegional(ctx) and !force) {
return
}
val fs = BufferedReader(InputStreamReader(ctx.assets.open("geoloc_state.txt")))
while (fs.ready()) {
val line = fs.readLine().split("|")
val state = State(line[0], line[2], line[3].toInt())
Country.entries.find { it.code == line[1] }?.children?.add(state)
val country = Country.entries.find { it.code == line[1] }
country?.children?.add(state)
country?.let {
if (Data.visits.getVisited(it) == NO_GROUP) {
Data.visits.setVisited(state, NO_GROUP)
}
}
}
}
fun clearStates() {
Country.entries.forEach { it.children.clear() }
Country.entries.forEach { country ->
if (country.children.any { region ->
Data.visits.getVisited(region) != NO_GROUP
}) {
if (Data.visits.getVisited(country) == NO_GROUP) {
Data.visits.setVisited(country, AUTO_GROUP)
}
}
country.children.clear()
}
Data.saveData()
}
}

View File

@ -2,10 +2,12 @@ package net.helcel.beans.countries
import net.helcel.beans.countries.Country.*
enum class Group(override val fullName: String, override val children: List<GeoLoc>) : GeoLoc {
enum class Group(override val fullName: String, override val children: Set<GeoLoc>) : GeoLoc {
EEE(
"Europe", listOf(
"Europe", setOf(
XAD,
ALA,// Åland Islands: an autonomous region of Finland, but not a member of the EU or UN
ALB,
AND,
AUT,
@ -18,14 +20,19 @@ enum class Group(override val fullName: String, override val children: List<GeoL
CZE,
DNK,
EST,
FRO, // Faroe Islands: an autonomous region of Denmark
FIN,
FRA,
DEU,
GIB, // Gibraltar: a British overseas territory located at the southern tip of the Iberian Peninsula
GRC,
GGY, // Guernsey: a British Crown dependency in the English Channel
HUN,
ISL,
IRL,
IMN, // Isle of Man: a British Crown dependency located in the Irish Sea
ITA,
JEY, // Jersey: a British Crown dependency located in the English Channel
KAZ,
XKO,
LVA,
@ -48,25 +55,28 @@ enum class Group(override val fullName: String, override val children: List<GeoL
SVK,
SVN,
ESP,
SJM, // Svalbard and Jan Mayen: an archipelago administered by Norway
SWE,
CHE,
UKR,
GBR,
VAT,
XAD,
)
),
ABB(
"Asia", listOf(
"Asia", setOf(
AFG,
ARM,
AZE,
BHR,
BGD,
BTN,
IOT, // British Indian Ocean Territory: a British overseas territory in the Indian Ocean
BRN,
KHM,
CCK, // Cocos (Keeling) Islands: an Australian external territory in the Indian Ocean
CHN,
CXR, // Christmas Island: an Australian external territory in the Indian Ocean
GEO,
HKG,
IND,
@ -111,7 +121,7 @@ enum class Group(override val fullName: String, override val children: List<GeoL
)
),
FFF(
"Africa", listOf(
"Africa", setOf(
DZA,
AGO,
BDI,
@ -131,8 +141,8 @@ enum class Group(override val fullName: String, override val children: List<GeoL
EGY,
GNQ,
ERI,
SWZ,
ETH,
ATF, // French Southern and Antarctic Lands: a territory of France located in the southern Indian Ocean
GAB,
GMB,
GHA,
@ -165,6 +175,7 @@ enum class Group(override val fullName: String, override val children: List<GeoL
SSD,
SHN,
SDN,
SWZ,
TZA,
TGO,
TUN,
@ -176,7 +187,7 @@ enum class Group(override val fullName: String, override val children: List<GeoL
)
),
NNN(
"North America", listOf(
"North America", setOf(
ABW,
AIA,
ATG,
@ -184,9 +195,11 @@ enum class Group(override val fullName: String, override val children: List<GeoL
BRB,
BLZ,
BMU,
BES, // Bonaire, Sint Eustatius and Saba: special municipalities of the Netherlands in the Caribbean
VGB,
CAN,
CYM,
XCL,
CRI,
CUB,
CUW,
@ -208,19 +221,22 @@ enum class Group(override val fullName: String, override val children: List<GeoL
NIC,
PAN,
PRI,
BLM, // Saint Barthélemy: an overseas collectivity of France in the Caribbean
KNA,
LCA,
MAF,
SPM,
VCT,
SXM, // Sint Maarten: a constituent country of the Kingdom of the Netherlands in the Caribbean
TTO,
TCA,
USA,
XCL,
UMI, // United States Minor Outlying Islands: a collection of nine insular areas of the United States
VIR, // United States Virgin Islands: an unincorporated territory of the United States in the Caribbean
)
),
SRR(
"South America", listOf(
"South America", setOf(
ARG,
BOL,
BRA,
@ -238,7 +254,7 @@ enum class Group(override val fullName: String, override val children: List<GeoL
)
),
UUU(
"Oceania", listOf(
"Oceania", setOf(
ASM,
AUS,
COK,
@ -257,6 +273,7 @@ enum class Group(override val fullName: String, override val children: List<GeoL
PLW,
PNG,
PCN,
WSM, // Samoa: an independent island nation in the South Pacific
SLB,
TKL,
TON,
@ -267,39 +284,22 @@ enum class Group(override val fullName: String, override val children: List<GeoL
),
XXX(
"Others", listOf(
"Others", setOf(
ATA, // Antarctica: not in any other region
ALA,// Åland Islands: an autonomous region of Finland, but not a member of the EU or UN
BES,// Bonaire, Sint Eustatius and Saba: special municipalities of the Netherlands in the Caribbean
BVT, // Bouvet Island: an uninhabited territory of Norway in the South Atlantic
IOT,// British Indian Ocean Territory: a British overseas territory in the Indian Ocean
CXR,// Christmas Island: an Australian external territory in the Indian Ocean
CCK,// Cocos (Keeling) Islands: an Australian external territory in the Indian Ocean
FRO,// Faroe Islands: an autonomous region of Denmark
ATF,// French Southern and Antarctic Lands: a territory of France located in the southern Indian Ocean
GIB,// Gibraltar: a British overseas territory located at the southern tip of the Iberian Peninsula
GGY,// Guernsey: a British Crown dependency in the English Channel
HMD, // Heard Island and McDonald Islands: an uninhabited Australian external territory in the southern Indian Ocean
IMN,// Isle of Man: a British Crown dependency located in the Irish Sea
JEY,// Jersey: a British Crown dependency located in the English Channel
BLM,// Saint Barthélemy: an overseas collectivity of France in the Caribbean
WSM, // Samoa: an independent island nation in the South Pacific
SXM, // Sint Maarten: a constituent country of the Kingdom of the Netherlands in the Caribbean
SGS, // South Georgia and the South Sandwich Islands: a British overseas territory in the southern Atlantic Ocean
SJM, // Svalbard and Jan Mayen: an archipelago administered by Norway
UMI, // United States Minor Outlying Islands: a collection of nine insular areas of the United States
VIR, // United States Virgin Islands: an unincorporated territory of the United States in the Caribbean
)
),
ZZZ(
"Undefined", listOf(
"Undefined", setOf(
)
),
NTT(
"NATO", listOf(
"NATO", setOf(
ALB, BEL, BGR, CAN, HRV, CZE, DNK, EST, FRA, DEU, GRC, HUN, ISL, ITA, LVA, LTU, LUX,
MNE, NLD, NOR, POL, PRT, ROU, SVK, SVN, ESP, TUR, GBR, USA
)

View File

@ -3,6 +3,17 @@ package net.helcel.beans.countries
class State(override val code: String, override val fullName: String, override val area: Int) :
GeoLoc {
override val children = emptyList<GeoLoc>()
override val children = emptySet<GeoLoc>()
override val type = GeoLoc.LocType.STATE
override fun hashCode(): Int {
return code.hashCode()
}
override fun equals(other: Any?): Boolean {
if (other is GeoLoc) {
return other.code == this.code
}
return false
}
}

View File

@ -2,19 +2,18 @@ package net.helcel.beans.countries
import net.helcel.beans.countries.Group.*
enum class World(override val fullName: String, override val children: List<GeoLoc>) : GeoLoc {
enum class World(override val fullName: String, override val children: Set<GeoLoc>) : GeoLoc {
WWW("World", listOf(
WWW(
"World", setOf(
EEE, ABB, FFF, NNN, SRR, UUU, XXX
));
)
);
override val area = children.fold(0) { acc, i ->
acc + i.area
}
override val type = GeoLoc.LocType.WORLD
override val code = this.name
}

View File

@ -10,13 +10,12 @@ import net.helcel.beans.countries.GeoLoc
import java.util.HashMap
object Data {
var visits : Visits = Visits(0, HashMap())
var groups : Groups = Groups(0,HashMap())
var selected_group : Groups.Group? = null
var selected_geoloc: GeoLoc? = null
var clearing_geoloc: GeoLoc? = null
private val groupsSerial = Groups.GroupsSerializer()
private val visitsSerial = Visits.VisitsSerializer()
@ -34,10 +33,9 @@ fun loadData(ctx: Context, id:Int) {
// Add default group "Visited" with app's color if there is no group already
if (groups.size() == 0) {
groups.setGroup(1, "Visited", ColorDrawable(ContextCompat.getColor(ctx, R.color.blue)))
groups.setGroup(DEFAULT_GROUP, "Visited", ColorDrawable(ContextCompat.getColor(ctx, R.color.blue)))
saveData()
}
}
fun saveData() {

View File

@ -0,0 +1,5 @@
package net.helcel.beans.helper
interface DialogCloser {
fun onDialogDismiss(clear: Boolean)
}

View File

@ -2,17 +2,24 @@ package net.helcel.beans.helper
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import androidx.core.content.ContextCompat
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.json.Json
import net.helcel.beans.R
import java.io.InputStream
import kotlin.coroutines.coroutineContext
import kotlin.random.Random
private const val randSeed = 0
private val rnd = Random(randSeed)
const val NO_GROUP = 0
const val DEFAULT_GROUP = 1
const val AUTO_GROUP = -1
@Serializable
class Groups(val id: Int, private val grps: HashMap<Int, Group>) {
@ -24,13 +31,18 @@ class Groups(val id: Int, private val grps: HashMap<Int, Group>) {
grps.remove(key)
}
fun deleteAllExcept(grp: Int) {
val keysToDelete = grps.keys.filter { it != grp }
keysToDelete.forEach { grps.remove(it) }
}
fun getGroupFromKey(key: Int): Group {
return grps.getOrDefault(key, EmptyGroup())
}
fun genKey(): Int {
val key = rnd.nextInt()
if (grps.containsKey(key) || key == 0) return genKey()
if (grps.containsKey(key) || key in listOf(NO_GROUP, DEFAULT_GROUP, AUTO_GROUP)) return genKey()
return key
}
@ -63,7 +75,7 @@ class Groups(val id: Int, private val grps: HashMap<Int, Group>) {
val key: Int,
val name: String,
@Serializable(with = Theme.ColorDrawableSerializer::class) val color: ColorDrawable = ColorDrawable(
Color.TRANSPARENT
Color.GRAY
)
)

View File

@ -4,12 +4,15 @@ import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import net.helcel.beans.R
import net.helcel.beans.activity.MainActivity
import net.helcel.beans.activity.fragment.SettingsFragment
object Settings {
private lateinit var sp: SharedPreferences
fun start(ctx: Context) {
private lateinit var mainActivity: MainActivity
fun start(ctx: MainActivity) {
mainActivity = ctx
sp = PreferenceManager.getDefaultSharedPreferences(ctx)
SettingsFragment.setTheme(
ctx, sp.getString(ctx.getString(R.string.key_theme), ctx.getString(R.string.system))
@ -37,6 +40,11 @@ object Settings {
)
}
fun refreshProjection(): Boolean {
mainActivity.refreshProjection()
return true
}
private fun getBooleanValue(ctx: Context, key: String?): Boolean {
return when (key) {
ctx.getString(R.string.on) -> true
@ -44,4 +52,18 @@ object Settings {
else -> false
}
}
fun getStats(ctx: Context, numerator: Int?, denominator: Int?): String {
if (numerator == null || denominator == null || denominator == 0) {
return ""
}
return when (getStatPref(ctx)) {
ctx.getString(R.string.percentages) -> ctx.getString(
R.string.percentage,
(100 * (numerator.toFloat() / denominator.toFloat())).toInt()
)
else -> ctx.getString(R.string.rate, numerator, denominator)
}
}
}

View File

@ -27,7 +27,7 @@ class Visits(val id: Int, private val locs: HashMap<String, Int>) {
}
fun getVisited(key: GeoLoc): Int {
return locs.getOrDefault(key.code, 0)
return getVisited(key.code)
}
private fun getVisited(key: String): Int {
@ -42,6 +42,19 @@ class Visits(val id: Int, private val locs: HashMap<String, Int>) {
return locs.keys.groupBy { getVisited(it) }
}
fun getVisitedByValue(key: Int): List<String> {
return locs.filter { it.value == key }.keys.toList()
}
fun reassignAllVisitedToGroup(group: Int) {
val keys = locs.filter { (_, grp) ->
grp !in listOf(NO_GROUP, AUTO_GROUP)
}.keys
keys.forEach {
locs[it] = group
}
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Visits::class)
class VisitsSerializer {

View File

@ -2,49 +2,64 @@ package net.helcel.beans.svg
import android.content.Context
import net.helcel.beans.countries.World
import net.helcel.beans.helper.AUTO_GROUP
import net.helcel.beans.helper.Data.groups
import net.helcel.beans.helper.Data.visits
import net.helcel.beans.helper.NO_GROUP
import net.helcel.beans.helper.Settings
import net.helcel.beans.helper.Theme.colorToHex6
import net.helcel.beans.helper.Theme.colorWrapper
class CSSWrapper(ctx: Context) {
class CSSWrapper(private val ctx: Context) {
private val colorForeground: String =
colorToHex6(colorWrapper(ctx, android.R.attr.panelColorBackground))
private val colorBackground: String =
colorToHex6(colorWrapper(ctx, android.R.attr.colorBackground))
private val baseCSS: String
private val continents: String = World.WWW.children.joinToString(",") { "#${it.code}2" }
private val countries: String = World.WWW.children.joinToString(",") { itt ->
itt.children.joinToString(",") { "#${it.code}2" }
}
private val regional: String = World.WWW.children.joinToString(",") { itt ->
itt.children.joinToString(",") { "#${it.code}1" }
}
private val countryOnlyCSS: String =
"svg{fill:$colorForeground;stroke:$colorBackground;stroke-width:0.1;}" +
"${regional}{display:none;}"
private val countryRegionalCSS: String =
"svg{fill:$colorForeground;stroke:$colorBackground;stroke-width:0.01;}" +
"$continents,$countries{fill:none;stroke:$colorBackground;stroke-width:0.1;}"
private var customCSS: String = ""
init {
val www = World.WWW.children.joinToString(",") { "#${it.code}2" }
val ccc = World.WWW.children.joinToString(",") { itt ->
itt.children.joinToString(",") { "#${it.code}2" }
}
baseCSS = "svg{fill:$colorForeground;stroke:$colorBackground;stroke-width:0.01;}" +
"$www,$ccc{stroke:$colorBackground;stroke-width:0.1;fill:none}"
refresh()
}
fun refresh() {
private fun refresh() {
val id = if (Settings.isRegional(ctx)) "1" else "2"
customCSS = visits.getVisitedByValue().map { (k, v) ->
if (groups.getGroupFromKey(k).key == 0)
""
else
v.joinToString(",") { "#${it}1,#${it}" } + "{fill:${
if (groups.getGroupFromKey(k).key != NO_GROUP || (!Settings.isRegional(ctx) && k == AUTO_GROUP)) {
v.joinToString(",") { "#${it}$id,#${it}" } + "{fill:${
colorToHex6(
groups.getGroupFromKey(
k
).color
if (k == AUTO_GROUP)
colorWrapper(ctx, android.R.attr.colorPrimary)
else groups.getGroupFromKey(k).color
)
};}"
} else {
""
}
}.joinToString("")
}
fun get(): String {
refresh()
return baseCSS + customCSS
return if (Settings.isRegional(ctx)) {
countryRegionalCSS + customCSS
} else {
countryOnlyCSS + customCSS
}
}
}

View File

@ -1,11 +1,25 @@
package net.helcel.beans.svg
import android.content.Context
import androidx.preference.PreferenceManager
import com.caverock.androidsvg.SVG
import net.helcel.beans.R
class SVGWrapper(ctx: Context) {
private var svg: SVG? = SVG.getFromAsset(ctx.assets, "mercator01.svg")
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx)
private val svgFile = when (sharedPreferences.getString(
ctx.getString(R.string.key_projection),
ctx.getString(R.string.mercator)
)) {
ctx.getString(R.string.azimuthalequidistant) -> "aeqd01.svg"
ctx.getString(R.string.equirectangular) -> "eqdc01.svg"
ctx.getString(R.string.loximuthal) -> "loxim01.svg"
ctx.getString(R.string.mercator) -> "webmercator01.svg"
else -> "webmercator01.svg"
}
private var svg: SVG? = SVG.getFromAsset(ctx.assets, svgFile)
fun get(): SVG? {
return svg

View File

@ -0,0 +1,10 @@
<vector
android:height="24dp"
android:viewportHeight="960"
android:viewportWidth="960"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="M346,820L100,574Q90,564 85,552Q80,540 80,527Q80,514 85,502Q90,490 100,480L330,251L224,145L286,80L686,480Q696,490 700.5,502Q705,514 705,527Q705,540 700.5,552Q696,564 686,574L440,820Q430,830 418,835Q406,840 393,840Q380,840 368,835Q356,830 346,820ZM393,314L179,528Q179,528 179,528Q179,528 179,528L607,528Q607,528 607,528Q607,528 607,528L393,314ZM792,840Q756,840 731,814.5Q706,789 706,752Q706,725 719.5,701Q733,677 750,654L792,600L836,654Q852,677 866,701Q880,725 880,752Q880,789 854,814.5Q828,840 792,840Z"/>
</vector>

View File

@ -8,34 +8,34 @@
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeColor="?attr/colorOnBackground"
android:strokeLineCap="round"/>
<path
android:pathData="M51,25v31c0,2.209 -1.791,4 -4,4H25c-2.209,0 -4,-1.791 -4,-4V25"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeColor="?attr/colorOnBackground"
android:strokeLineCap="round"/>
<path
android:pathData="M17,16h38v4h-38z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeColor="?attr/colorOnBackground"
android:strokeLineCap="round"/>
<path
android:pathData="M41,28.25L41,55"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeColor="?attr/colorOnBackground"
android:strokeLineCap="round"/>
<path
android:pathData="M31,28.25L31,55"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeColor="?attr/colorOnBackground"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android" >
<path android:fillColor="?attr/colorOnBackground" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
<path android:fillColor="?attr/colorPrimary" android:pathData="M8,14m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path android:fillColor="?attr/colorPrimary" android:pathData="M12,8m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path android:fillColor="?attr/colorPrimary" android:pathData="M16,14m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
</vector>

View File

@ -5,6 +5,6 @@
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@color/blue"
android:fillColor="@color/darkgray"
android:pathData="M0,0h960v960h-960z" />
</vector>

View File

@ -1,13 +1,50 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportWidth="1600"
android:viewportHeight="1600">
android:width="108dp"
android:height="108dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group android:scaleX="0.8918919"
android:scaleY="0.8918919"
android:translateX="6.918919"
android:translateY="6.918919">
<group
android:scaleX="1.5"
android:scaleY="1.5"
android:translateX="10"
android:translateY="10">
<path
android:pathData="M36,36m-28,0a28,28 0,1 1,56 0a28,28 0,1 1,-56 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="@color/blue"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</group>
<group
android:scaleX="1.25"
android:scaleY="1.25"
android:translateX="18"
android:translateY="18">
<path
android:pathData="M56.803,45.75c0.599,-0.299 1.157,-0.672 1.663,-1.11 0.804,-0.698 1.463,-1.546 1.94,-2.497 0.599,-1.303 0.883,-2.728 0.829,-4.161 0.034,-1.498 -0.154,-2.994 -0.558,-4.437 -0.451,-1.645 -1.104,-3.229 -1.944,-4.714 -0.967,-2.141 -2.28,-4.108 -3.887,-5.822 -1.242,-1.326 -2.757,-2.366 -4.44,-3.048 -0.877,-0.372 -1.821,-0.56 -2.774,-0.553 -1.402,0.074 -2.729,0.697 -3.882,1.389 -1.285,0.81 -2.244,1.735 -2.771,3.053 -0.739,2.362 0.827,4.821 1.113,5.269 0.003,0.005 0.187,0.281 0.555,0.832 1.512,2.264 1.589,2.358 1.666,2.495 0.646,1.221 1.114,2.528 1.389,3.882 1.043,4.001 1.565,6.001 2.223,6.932 1.208,1.71 3.455,3.414 5.826,3.325 1.059,-0.088 2.093,-0.371 3.05,-0.835Z"
android:strokeWidth="2"
android:fillColor="@color/white"
android:fillType="nonZero"
android:pathData="m800,1200q-83,0 -156,-31.5Q571,1137 517,1083 463,1029 431.5,956 400,883 400,800 400,717 431.5,644 463,571 517,517 571,463 644,431.5 717,400 800,400q83,0 156,31.5 73,31.5 127,85.5 54,54 85.5,127 31.5,73 31.5,156 0,83 -31.5,156 -31.5,73 -85.5,127 -54,54 -127,85.5 -73,31.5 -156,31.5zM800,1120q134,0 227,-93 93,-93 93,-227 0,-7 -0.5,-14.5 -0.5,-7.5 -0.5,-12.5 -5,29 -27,48 -22,19 -52,19L960,840Q927,840 903.5,816.5 880,793 880,760L880,720L720,720v-80q0,-33 23.5,-56.5Q767,560 800,560h40v0q0,-23 12.5,-40.5Q865,502 883,491q-20,-5 -40.5,-8 -20.5,-3 -42.5,-3 -134,0 -227,93 -93,93 -93,227 0,0 0,0 0,0 0,0h200q66,0 113,47 47,47 47,113v40L720,1000v110q20,5 39.5,7.5 19.5,2.5 40.5,2.5z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M22,41c-1.54,0.554 -2.83,1.642 -3.636,3.066 -0.714,1.365 -0.957,2.928 -0.693,4.445 0.178,1.247 0.632,2.439 1.329,3.488 2.032,3.228 5.383,4.423 7,5 1.613,0.561 3.295,0.897 5,1 2.387,0.205 6.923,0.535 11,-2 1.287,-0.665 2.335,-1.713 3,-3 0.661,-1.601 0.661,-3.399 0,-5 -0.389,-1.156 -1.121,-2.165 -2.099,-2.894 -0.919,-0.599 -1.974,-0.956 -3.069,-1.039 -2.057,-0.313 -2.756,0.139 -5.014,0.057 -1.271,-0.019 -2.534,-0.214 -3.753,-0.577 -3.036,-0.95 -3.33,-2.457 -5.889,-2.829 -1.066,-0.158 -2.155,-0.061 -3.177,0.282Z"
android:strokeWidth="2"
android:fillColor="@color/red"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M12.7,26.975c1.758,-3.604 5.311,-3.191 9.58,-7.091 2.701,-2.469 2.858,-4.078 5.613,-5.202 1.407,-0.644 2.984,-0.819 4.498,-0.5 2.053,0.475 3.761,1.891 4.61,3.819 1.116,2.742 -0.314,5.437 -1.398,7.482 -0.951,1.689 -2.167,3.215 -3.602,4.518 -1.479,1.552 -3.161,2.898 -5,4 -2.629,1.541 -6.332,3.711 -9.989,2.43 -1.481,-0.548 -2.768,-1.521 -3.699,-2.796 -1.496,-1.906 -1.735,-4.512 -0.612,-6.659Z"
android:strokeWidth="2"
android:fillColor="@color/green"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</group>
</group>
</vector>

View File

@ -0,0 +1,16 @@
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android" >
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="M20.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48L3,20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48L21,3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM10,5.47l4,1.4v11.66l-4,-1.4L10,5.47zM5,6.46l3,-1.01v11.7l-3,1.16L5,6.46zM19,17.54l-3,1.01L16,6.86l3,-1.16v11.84z" />
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M15,18.89l-6,-2.11L9,5.11l6,2.11v11.67z"/>
</vector>

View File

@ -7,7 +7,7 @@
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10c1.38,0 2.5,-1.12 2.5,-2.5c0,-0.61 -0.23,-1.2 -0.64,-1.67c-0.08,-0.1 -0.13,-0.21 -0.13,-0.33c0,-0.28 0.22,-0.5 0.5,-0.5H16c3.31,0 6,-2.69 6,-6C22,6.04 17.51,2 12,2zM17.5,13c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5C19,12.33 18.33,13 17.5,13zM14.5,9C13.67,9 13,8.33 13,7.5C13,6.67 13.67,6 14.5,6S16,6.67 16,7.5C16,8.33 15.33,9 14.5,9zM5,11.5C5,10.67 5.67,10 6.5,10S8,10.67 8,11.5C8,12.33 7.33,13 6.5,13S5,12.33 5,11.5zM11,7.5C11,8.33 10.33,9 9.5,9S8,8.33 8,7.5C8,6.67 8.67,6 9.5,6S11,6.67 11,7.5z" />
android:pathData="M12,22C6.49,22 2,17.51 2,12S6.49,2 12,2s10,4.04 10,9c0,3.31 -2.69,6 -6,6h-1.77c-0.28,0 -0.5,0.22 -0.5,0.5c0,0.12 0.05,0.23 0.13,0.33c0.41,0.47 0.64,1.06 0.64,1.67C14.5,20.88 13.38,22 12,22zM12,4c-4.41,0 -8,3.59 -8,8s3.59,8 8,8c0.28,0 0.5,-0.22 0.5,-0.5c0,-0.16 -0.08,-0.28 -0.14,-0.35c-0.41,-0.46 -0.63,-1.05 -0.63,-1.65c0,-1.38 1.12,-2.5 2.5,-2.5H16c2.21,0 4,-1.79 4,-4C20,7.14 16.41,4 12,4z" />
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M17.5,13c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5C19,12.33 18.33,13 17.5,13zM14.5,9C13.67,9 13,8.33 13,7.5C13,6.67 13.67,6 14.5,6S16,6.67 16,7.5C16,8.33 15.33,9 14.5,9zM5,11.5C5,10.67 5.67,10 6.5,10S8,10.67 8,11.5C8,12.33 7.33,13 6.5,13S5,12.33 5,11.5zM11,7.5C11,8.33 10.33,9 9.5,9S8,8.33 8,7.5C8,6.67 8.67,6 9.5,6S11,6.67 11,7.5z" />

View File

@ -0,0 +1,12 @@
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android" >
<path android:fillColor="?attr/colorOnBackground" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
<path android:fillColor="?attr/colorPrimary" android:pathData="M12,10h-2v2H9v-2H7V9h2V7h1v2h2v1z"/>
</vector>

View File

@ -1,15 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:theme="@style/Theme.Beans"
tools:context=".activity.StatActivity">
tools:context=".activity.StatsActivity">
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/chart"
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="gone" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/group_color"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:paddingStart="56dp"
android:text="@string/total"
android:textAlignment="textStart"
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlSymmetry" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="start|center_vertical"
android:paddingStart="20dp"
android:paddingEnd="52dp"
android:text=""
android:textColor="?attr/colorOnPrimary"
app:layout_constraintBottom_toBottomOf="@id/group_color"
app:layout_constraintEnd_toEndOf="@id/group_color"
app:layout_constraintTop_toTopOf="@id/group_color" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/stats"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -12,12 +12,11 @@
android:orientation="vertical">
<com.google.android.material.imageview.ShapeableImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginTop="40dp"
android:layout_marginBottom="30dp"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_marginTop="20dp"
android:contentDescription="@string/logo"
android:src="@mipmap/ic_launcher_round" />
android:src="@drawable/ic_launcher_foreground" />
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"

View File

@ -6,6 +6,12 @@
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/warning_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -0,0 +1,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="net.helcel.beans.activity.EditActivity" >
<item
android:id="@+id/action_color"
android:orderInCategory="100"
android:icon="@drawable/color"
android:title="@string/action_color"
app:showAsAction="ifRoom" />
</menu>

View File

@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -15,4 +15,12 @@
<item>@string/on</item>
<item>@string/off</item>
</string-array>
<string-array name="map_projection">
<item>@string/azimuthalequidistant</item>
<item>@string/equirectangular</item>
<item>@string/loximuthal</item>
<item>@string/mercator</item>
</string-array>
</resources>

View File

@ -2,12 +2,12 @@
<resources>
<color name="black">#FF000000</color>
<color name="darkgray">#FF0C1D2E</color>
<color name="gray">#425F7C</color>
<color name="lightgray">#FF93A9BE</color>
<color name="white">#FFFFFFFF</color>
<color name="green">#93F531</color>
<color name="blue">#3193F5</color>
<color name="red">#F53131</color>
<color name="white">#FFF0F3F7</color>
<color name="blue">#0d5cab</color>
<color name="green">#B9F57D</color>
<color name="red">#F57D7D</color>
</resources>

View File

@ -5,6 +5,7 @@
<string name="action_settings">Settings</string>
<string name="action_stat">Stats</string>
<string name="action_edit">Edit</string>
<string name="action_color">Color</string>
<string name="key_theme">App theme</string>
<string name="system">System</string>
<string name="light">Light</string>
@ -20,7 +21,10 @@
<string name="beans_repo">Project repository: https://git.helcel.net/helcel/beans\n Feel free to report issues or contribute to the project.</string>
<string name="foss_licenses">Free and open source dependencies and licenses</string>
<string name="about_beans">About the Beans application</string>
<string name="edit_group">Select the group to assign. Long press on a group to edit its name and color.</string>
<string name="delete_group">Are your sure you want to delete this group and remove all its country mappings?</string>
<string name="select_group">Select one group you want to keep. All others will be deleted and its mappings reassigned to the group you choose here.</string>
<string name="delete_regions">Are you sure you want to disable regions and reassign all regional mappings to the corresponding countries?</string>
<string name="add">Add</string>
<string name="clear">Clear</string>
<string name="logo">Logo</string>
@ -34,4 +38,11 @@
<string name="delete">Delete</string>
<string name="cancel">Cancel</string>
<string name="ok">Ok</string>
<string name="total">Total</string>
<string name="uncategorized">Uncategorized</string>
<string name="azimuthalequidistant">Azimuthal Equidistant</string>
<string name="equirectangular">Equirectangular</string>
<string name="mercator">Mercator</string>
<string name="loximuthal">Loximuthal</string>
<string name="key_projection">Map Projection</string>
</resources>

View File

@ -4,23 +4,23 @@
android:theme="@style/Theme.Beans">
<ListPreference
app:defaultValue="@string/off"
app:defaultValue="@string/system"
app:enabled="true"
app:entries="@array/entries_onoff"
app:entryValues="@array/entries_onoff"
app:icon="@drawable/edit"
app:key="@string/key_group"
app:title="@string/key_group"
app:entries="@array/entries_theme"
app:entryValues="@array/entries_theme"
app:icon="@drawable/palette"
app:key="@string/key_theme"
app:title="@string/key_theme"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:defaultValue="@string/off"
app:defaultValue="@string/mercator"
app:enabled="true"
app:entries="@array/entries_onoff"
app:entryValues="@array/entries_onoff"
app:icon="@drawable/edit"
app:key="@string/key_regional"
app:title="@string/key_regional"
app:entries="@array/map_projection"
app:entryValues="@array/map_projection"
app:icon="@drawable/map"
app:key="@string/key_projection"
app:title="@string/key_projection"
app:useSimpleSummaryProvider="true" />
<ListPreference
@ -34,18 +34,30 @@
app:useSimpleSummaryProvider="true" />
<ListPreference
app:defaultValue="@string/system"
app:defaultValue="@string/off"
app:enabled="true"
app:entries="@array/entries_theme"
app:entryValues="@array/entries_theme"
app:icon="@drawable/palette"
app:key="@string/key_theme"
app:title="@string/key_theme"
app:allowDividerAbove="true"
app:entries="@array/entries_onoff"
app:entryValues="@array/entries_onoff"
app:icon="@drawable/group"
app:key="@string/key_group"
app:title="@string/key_group"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:defaultValue="@string/off"
app:enabled="true"
app:entries="@array/entries_onoff"
app:entryValues="@array/entries_onoff"
app:icon="@drawable/zoomin"
app:key="@string/key_regional"
app:title="@string/key_regional"
app:useSimpleSummaryProvider="true" />
<Preference
android:summary="@string/foss_licenses"
app:enabled="true"
app:allowDividerAbove="true"
app:icon="@drawable/licenses"
app:key="@string/licenses"
app:title="@string/licenses" />

View File

@ -58,12 +58,25 @@ const groups = {
var dict0 = {}
var dict1 = {}
const formatStr = (str)=> str.replace(/(?<!\b\w)\B[A-Z]|,(?!$)/g, match => {
const formatStr = (str)=> str.replace(/(?<!\b\w\u00E0-\u00FC)\B[A-Z\u00C0-\u00DC]|,(?!$)/g, match => {
if (match.startsWith(',')) {
return ', ';
} else {
return ' ' + match;
}})
}}).replace("ofthe "," of the ").replace("dela ", " de la ").replace("delos ", " de los ").replace("áD","á D")
.replace("Côted'","Côte d'").replace("leof ","le of ").replace("dde ","d de ").replace("iode ","io de ").replace("àde ","à de ")
.replace("yof ","y of ").replace("Andrésy ","Andrés y")
.replace("aand ","a and ").replace("iand ", "i and ").replace("tsand ","ts and ").replace("onand ","on and ").replace("reand ", "re and ")
.replace("odel ","o del ").replace("adel ", "a del ").replace("ndel ","n del ").replace("zdel ","z del ").replace("falde ", "fal de ").replace("casdel ","cas del ")
.replace("odosÓ", "o dos Ó")
.replace("Grandedo ", "Grande do ").replace("Grandede ","Grande de ")
.replace("Santiagode ","Santiago de ").replace("Joséde ","José de ").replace("Pedrode ","Pedro de ")
.replace("andthe "," and the ")
.replace("emunicipality", "e municipality").replace("Villede ", "Ville de ")
.replace("Valledel ","Valle del ").replace("Valde ","Val de ").replace("Îlesdu ","Îles du ")
.replace("sÉ","s É").replace("áO","á O").replace("N C Tof ","NCT of ").replace("N A","NA")
.replace("Nortede ", "Norte de ")
.trim()
const parse0 = (country) => {
const filepath = `temp/0/${country}.json`

View File

@ -6,6 +6,7 @@ GADM_VERSION="4.1"
GADM_BASEPATH="https://geodata.ucdavis.edu/gadm"
mapshaper="./node_modules/mapshaper/bin/mapshaper"
ATA_URL="https://media.githubusercontent.com/media/wmgeolab/geoBoundaries/905b0baf5f4fb3b9ccf45293647dcacdb2b799d4/releaseData/gbOpen/ATA/ADM0/geoBoundaries-ATA-ADM0_simplified.geojson"
countries=(
"AFG" "XAD" "ALA" "ALB" "DZA" "ASM" "AND" "AGO" "AIA" "ATG" "ARG" "ARM" "ABW" "AUS" "AUT" "AZE"
@ -67,7 +68,10 @@ download_1() {
jq '.features[] |= . + {properties: (.properties | .GID_1 = (.GID_0 + "_" + (
if .HASC_1 != "NA" then (.HASC_1 | split(".") | .[-1])
elif .ISO_1 != "NA" then (.ISO_1 | split("-") | .[-1])
else (.CC_1)
elif .CC_1 != "NA" then (.CC_1)
elif .NAME_1 != "NA" then (.NAME_1)
elif .GID_1 != "NA" then (.GID_1 | split(".") | .[-1])
else .GID_1
end
)))}' "$output_dir/gadm41_${1}_1.json" > "$output_dir/$1.json.1"
sed -E 's/"[gadm41_]*([A-Z]*)_1"/"\1"/g' "$output_dir/$1.json.1" > "$output_dir/$1.json"
@ -76,7 +80,7 @@ download_1() {
toSVG_0() {
local input_files=()
local input_files=("ATA")
for country in "${countries[@]}"
do
@ -94,7 +98,7 @@ toSVG_0() {
}
toSVG_1() {
input_files=()
input_files=("ATA")
for country in "${countries[@]}"
do
@ -113,12 +117,12 @@ toSVG_1() {
toSVG_01() {
input_files=()
input_files=("./temp/1/ATA.json" "./temp/0/ATA.json")
for country in "${countries[@]}"
do
input_file0="./temp/0/${country}.json"
input_file1="./temp/1/${country}.json"
input_file0="./temp/0/${country}.json"
if [ -f "$input_file1" ]; then
input_files+=("$input_file1")
fi
@ -127,8 +131,11 @@ toSVG_01() {
fi
done
"$mapshaper" -i combine-files ${input_files[@]} -proj webmercator -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/mercator01.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
"$mapshaper" -i combine-files ${input_files[@]} -proj aeqd +lat_0=90 -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/aeqd01.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
"$mapshaper" -i combine-files ${input_files[@]} snap -proj eqdc +lat_1=55 +lat_2=60 -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/eqdc01.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
"$mapshaper" -i combine-files ${input_files[@]} snap -proj loxim densify -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/loxim01.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
"$mapshaper" -i combine-files ${input_files[@]} snap -proj webmercator densify -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/webmercator01.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
"$mapshaper" -i combine-files ${input_files[@]} snap -proj aeqd +lat_0=90 densify -simplify 0.005 weighted keep-shapes resolution=1200x1200 -o ./app/src/main/assets/aeqd01.svg svg-data=GID_0,COUNTRY,GID,NAME id-field=GID
}
do_1() {
@ -136,15 +143,17 @@ do_1() {
do
download_1 "$country"
done
wget -q -O "./temp/1/ATA.json" "$ATA_URL"
}
do_0() {
for country in "${countries[@]}"
do
download_0 "$country"
done
wget -q -O "./temp/1/ATA.json" "$ATA_URL"
}
# do_0
do_0
do_1
# toSVG_0
toSVG_1
# toSVG_1
toSVG_01

5329
yarn.lock

File diff suppressed because it is too large Load Diff