From 7746e63373c905faa6d7e45e45fffc48d3ffff85 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Thu, 3 Aug 2017 22:21:51 -0700 Subject: Add IM notifications, FAQ, video uploading, and geolocations (#107) * Test canary * Update activities to use kau base * Update dependencies * Cherry pick faq * Update kau and add faq * Add readme badges * Add im notifications and video uploading * Update theme * Update and fix unit tests * Add geolocation * Prepare alpha test * Remove explicit nonnull request --- README.md | 3 + app/build.gradle | 90 +++++++++++----------- app/src/main/AndroidManifest.xml | 17 ++-- app/src/main/assets/css/core/main.compact.css | 6 +- app/src/main/assets/css/core/main.scss | 6 +- app/src/main/assets/css/themes/custom.compact.css | 6 +- .../assets/css/themes/material_amoled.compact.css | 6 +- .../assets/css/themes/material_dark.compact.css | 6 +- .../assets/css/themes/material_glass.compact.css | 6 +- .../assets/css/themes/material_light.compact.css | 6 +- app/src/main/assets/js/notif_msg.js | 25 ++++++ app/src/main/assets/js/notif_msg.min.js | 17 ++++ .../kotlin/com/pitchedapps/frost/StartActivity.kt | 4 +- .../pitchedapps/frost/activities/AboutActivity.kt | 9 +++ .../pitchedapps/frost/activities/BaseActivity.kt | 6 +- .../pitchedapps/frost/activities/ImageActivity.kt | 10 +-- .../frost/activities/ImagePickerActivity.kt | 12 --- .../pitchedapps/frost/activities/IntroActivity.kt | 27 ++++--- .../pitchedapps/frost/activities/MainActivity.kt | 25 +++--- .../frost/activities/MediaPickerActivity.kt | 10 +++ .../frost/activities/SettingsActivity.kt | 12 ++- .../frost/activities/WebOverlayActivity.kt | 12 +-- .../com/pitchedapps/frost/contracts/FileChooser.kt | 23 +++--- .../pitchedapps/frost/facebook/FbUrlFormatter.kt | 35 +++++---- .../com/pitchedapps/frost/injectors/CssAssets.kt | 1 - .../com/pitchedapps/frost/injectors/JsActions.kt | 4 +- .../com/pitchedapps/frost/injectors/JsAssets.kt | 2 +- .../frost/services/NotificationService.kt | 63 +++++++-------- .../com/pitchedapps/frost/settings/Appearance.kt | 2 +- .../com/pitchedapps/frost/settings/Experimental.kt | 4 +- .../kotlin/com/pitchedapps/frost/utils/Prefs.kt | 3 +- .../kotlin/com/pitchedapps/frost/utils/Utils.kt | 9 ++- .../com/pitchedapps/frost/utils/WebContextMenu.kt | 1 + .../com/pitchedapps/frost/utils/iab/IABBinder.kt | 4 + .../com/pitchedapps/frost/views/BadgedIcon.kt | 2 - .../pitchedapps/frost/web/FrostChromeClients.kt | 16 +++- .../com/pitchedapps/frost/web/FrostWebView.kt | 3 +- .../pitchedapps/frost/web/FrostWebViewClients.kt | 6 +- .../com/pitchedapps/frost/web/MessageWebView.kt | 58 ++++++-------- app/src/main/play/en-CA/listing/fulldescription | 9 ++- app/src/main/res/layout/intro_end.xml | 2 +- app/src/main/res/values/colors.xml | 3 - app/src/main/res/values/strings.xml | 4 +- app/src/main/res/values/strings_about.xml | 23 ++++++ .../main/res/values/strings_pref_notifications.xml | 2 + app/src/main/res/values/strings_preferences | 20 ----- app/src/main/res/values/strings_preferences.xml | 24 ++++++ app/src/main/res/xml/frost_changelog.xml | 13 +++- app/src/main/res/xml/frost_faq.xml | 17 ++++ .../com/pitchedapps/frost/facebook/FbUrlTest.kt | 18 ++--- build.gradle | 4 +- docs/Changelog.md | 12 +++ gradle.properties | 9 +-- gradle/wrapper/gradle-wrapper.properties | 4 +- 54 files changed, 428 insertions(+), 293 deletions(-) create mode 100644 app/src/main/assets/js/notif_msg.js create mode 100644 app/src/main/assets/js/notif_msg.min.js delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt create mode 100644 app/src/main/kotlin/com/pitchedapps/frost/activities/MediaPickerActivity.kt create mode 100644 app/src/main/res/values/strings_about.xml delete mode 100644 app/src/main/res/values/strings_preferences create mode 100644 app/src/main/res/values/strings_preferences.xml create mode 100644 app/src/main/res/xml/frost_faq.xml diff --git a/README.md b/README.md index 0a347c2b..cf2a0fb4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Frost-for-Facebook +[![Build Status](https://travis-ci.org/AllanWang/Frost-for-Facebook.svg?branch=master)](https://travis-ci.org/AllanWang/Frost-for-Facebook) +[![Stories in Ready](https://badge.waffle.io/AllanWang/Frost-for-Facebook.png?label=ready&title=Ready)](https://waffle.io/AllanWang/Frost-for-Facebook?utm_source=badge) + Get it on Google Play Frost is a third party Facebook wrapper geared towards design and functionality. diff --git a/app/build.gradle b/app/build.gradle index 98179294..624c04ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,13 +33,13 @@ android { versionCode androidGitVersion.code() versionName androidGitVersion.name() multiDexEnabled true + buildTypeMatching 'release' testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } applicationVariants.all { variant -> - variant.outputs.each { output -> - output.outputFile = new File(output.outputFile.parent, - "${project.APP_ID}-${variant.buildType.name}.apk") + variant.outputs.all { + outputFileName = "${project.APP_ID}-${variant.buildType.name}.apk" } } @@ -78,7 +78,7 @@ android { shrinkResources false applicationIdSuffix ".debug" versionNameSuffix "-debug" - resValue "string", "app_name", "Frost Debug" + resValue "string", "frost_name", "Frost Debug" resValue "string", "frost_web", "Frost Web Debug" ext.enableCrashlytics = false } @@ -89,7 +89,7 @@ android { applicationIdSuffix ".test" signingConfig signingConfigs.test versionNameSuffix "-test" - resValue "string", "app_name", "Frost Test" + resValue "string", "frost_name", "Frost Test" resValue "string", "frost_web", "Frost Web Test" } release { @@ -97,7 +97,7 @@ android { shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release - resValue "string", "app_name", "Frost" + resValue "string", "frost_name", "Frost" resValue "string", "frost_web", "Frost Web" } } @@ -113,64 +113,68 @@ android { } repositories { + google() jcenter() - mavenCentral() maven { url "https://jitpack.io" } - maven { url 'https://maven.google.com' } maven { url 'https://maven.fabric.io/public' } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.3-alpha', { + androidTestImplementation('com.android.support.test.espresso:espresso-core:2.3-alpha', { exclude group: 'com.android.support', module: 'support-annotations' }) - testCompile 'junit:junit:4.12' - testCompile "org.robolectric:robolectric:${ROBOELECTRIC}" - - compile "ca.allanwang.kau:about:$KAU" - compile "ca.allanwang.kau:colorpicker:$KAU" - compile "ca.allanwang.kau:imagepicker:$KAU" - compile "ca.allanwang.kau:kpref-activity:$KAU" - compile "ca.allanwang.kau:searchview:$KAU" - - testCompile "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}" - - debugCompile "com.squareup.leakcanary:leakcanary-android:${LEAK_CANARY}" - releaseTestCompile "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" - releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" - testCompile "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" - - compile "com.github.Raizlabs.DBFlow:dbflow:${DBFLOW}" - compile "com.github.Raizlabs.DBFlow:dbflow-core:${DBFLOW}" + testImplementation 'junit:junit:4.12' + testImplementation "org.robolectric:robolectric:${ROBOELECTRIC}" + + //noinspection GradleDependency + implementation "ca.allanwang.kau:adapter:$KAU" + //noinspection GradleDependency + implementation "ca.allanwang.kau:about:$KAU" + //noinspection GradleDependency + implementation "ca.allanwang.kau:colorpicker:$KAU" + //noinspection GradleDependency + implementation "ca.allanwang.kau:mediapicker:$KAU" + //noinspection GradleDependency + implementation "ca.allanwang.kau:kpref-activity:$KAU" + //noinspection GradleDependency + implementation "ca.allanwang.kau:searchview:$KAU" + //noinspection GradleDependency + implementation "ca.allanwang.kau:core-ui:$KAU" + + testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}" + + debugImplementation "com.squareup.leakcanary:leakcanary-android:${LEAK_CANARY}" + releaseTestImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" + releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" + testImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" + + implementation "com.github.Raizlabs.DBFlow:dbflow:${DBFLOW}" + implementation "com.github.Raizlabs.DBFlow:dbflow-core:${DBFLOW}" kapt "com.github.Raizlabs.DBFlow:dbflow-processor:${DBFLOW}" - compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${DBFLOW}" + implementation "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${DBFLOW}" //Icons - compile "com.mikepenz:material-design-iconic-typeface:${IICON_MATERIAL}@aar" - compile "com.mikepenz:community-material-typeface:${IICON_COMMUNITY}@aar" + implementation "com.mikepenz:material-design-iconic-typeface:${IICON_MATERIAL}@aar" + implementation "com.mikepenz:community-material-typeface:${IICON_COMMUNITY}@aar" - compile "org.jsoup:jsoup:${JSOUP}" + implementation "org.jsoup:jsoup:${JSOUP}" - compile "com.squareup.okhttp3:okhttp:${OKHTTP}" + implementation "com.squareup.okhttp3:okhttp:${OKHTTP}" - compile "com.anjlab.android.iab.v3:library:${IAB}" + implementation "com.anjlab.android.iab.v3:library:${IAB}" -// compile("com.mikepenz:materialdrawer:${MATERIAL_DRAWER}@aar") { -// transitive = true -// } - compile "co.zsmb:materialdrawer-kt:${MATERIAL_DRAWER_KT}" + implementation "co.zsmb:materialdrawer-kt:${MATERIAL_DRAWER_KT}" - compile "nz.bradcampbell:paperparcel:${PAPER_PARCEL}" - compile "nz.bradcampbell:paperparcel-kotlin:${PAPER_PARCEL}" + implementation "nz.bradcampbell:paperparcel:${PAPER_PARCEL}" + implementation "nz.bradcampbell:paperparcel-kotlin:${PAPER_PARCEL}" kapt "nz.bradcampbell:paperparcel-compiler:${PAPER_PARCEL}" - compile("com.crashlytics.sdk.android:crashlytics:${CRASHLYTICS}@aar") { + implementation("com.crashlytics.sdk.android:crashlytics:${CRASHLYTICS}@aar") { transitive = true; } - compile "com.davemorrissey.labs:subsampling-scale-image-view:${SCALE_IMAGE_VIEW}" + implementation "com.davemorrissey.labs:subsampling-scale-image-view:${SCALE_IMAGE_VIEW}" - compile "com.sothree.slidinguppanel:library:${SLIDING_PANEL}" + implementation "com.sothree.slidinguppanel:library:${SLIDING_PANEL}" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c4275ae6..c4b5b9dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,8 @@ + + @@ -18,13 +20,13 @@ android:allowBackup="true" android:fullBackupContent="@xml/frost_backup_rules" android:icon="@mipmap/ic_launcher_round" - android:label="@string/app_name" + android:label="@string/frost_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/FrostTheme.Splash"> @@ -36,12 +38,12 @@ android:name=".activities.MainActivity" android:configChanges="orientation|screenSize|locale" android:hardwareAccelerated="true" - android:label="@string/app_name" + android:label="@string/frost_name" android:theme="@style/FrostTheme" /> + android:theme="@style/FrostTheme.Transparent" /> + android:theme="@style/Kau.MediaPicker.Overlay" /> + *, .al, ._44qk, ._1gkq, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._3on6, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child, ._5fjv, ._5fjw, ._4z83 { border-bottom: 1px solid rgba(215, 176, 215, 0.3) !important; } -._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(215, 176, 215, 0.3) !important; } +._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(215, 176, 215, 0.3) !important; } ._4o58::after, .acw, .aclb, ._4qax, ._5h8f { border-color: rgba(215, 176, 215, 0.3) !important; } diff --git a/app/src/main/assets/css/core/main.scss b/app/src/main/assets/css/core/main.scss index 6f7c6190..5f532cf4 100644 --- a/app/src/main/assets/css/core/main.scss +++ b/app/src/main/assets/css/core/main.scss @@ -33,7 +33,7 @@ body, #root, #header, [style*="background-color"], ._55wo, ._1upc, input, ._2f9r background: $bg_opaque2 !important; } -button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, +button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._2cpp, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, @@ -41,7 +41,7 @@ button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS background: $background2 !important; } -[style*="color"], body, input, ._42rv, +[style*="color"], body, input, ._42rv, ._4qau, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, @@ -78,7 +78,7 @@ h1, h2, h3, h4, h5, h6 { //friend card border ._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, -._1_y5, ._lr0, ._5hgt, +._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid $divider !important; } diff --git a/app/src/main/assets/css/themes/custom.compact.css b/app/src/main/assets/css/themes/custom.compact.css index b9cad06d..e8add9c8 100644 --- a/app/src/main/assets/css/themes/custom.compact.css +++ b/app/src/main/assets/css/themes/custom.compact.css @@ -10,9 +10,9 @@ body, #root, #header, [style*="background-color"], ._55wo, ._1upc, input, ._2f9r ._403n, ._1-kc { background: $OO$ !important; } -button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: $BBT$ !important; } +button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._2cpp, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: $BBT$ !important; } -[style*="color"], body, input, ._42rv, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: $T$ !important; } +[style*="color"], body, input, ._42rv, ._4qau, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: $T$ !important; } ._15kl::before, ._5j35::after, ._2k4b, ._3to7, ._4nw8 { border-left: 1px solid $D$ !important; } @@ -22,7 +22,7 @@ button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS ._15ny::after, ._z-w, ._8i2, ._2nk0, ._2u4w, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .jx-result, ._2om3, ._2ol-, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._1gkq, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._3on6, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child, ._5fjv, ._5fjw, ._4z83 { border-bottom: 1px solid $D$ !important; } -._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid $D$ !important; } +._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid $D$ !important; } ._4o58::after, .acw, .aclb, ._4qax, ._5h8f { border-color: $D$ !important; } diff --git a/app/src/main/assets/css/themes/material_amoled.compact.css b/app/src/main/assets/css/themes/material_amoled.compact.css index f61519d1..576e755a 100644 --- a/app/src/main/assets/css/themes/material_amoled.compact.css +++ b/app/src/main/assets/css/themes/material_amoled.compact.css @@ -10,9 +10,9 @@ body, #root, #header, [style*="background-color"], ._55wo, ._1upc, input, ._2f9r ._403n, ._1-kc { background: #595959 !important; } -button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(89, 89, 89, 0.2) !important; } +button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._2cpp, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(89, 89, 89, 0.2) !important; } -[style*="color"], body, input, ._42rv, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; } +[style*="color"], body, input, ._42rv, ._4qau, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; } ._15kl::before, ._5j35::after, ._2k4b, ._3to7, ._4nw8 { border-left: 1px solid rgba(255, 255, 255, 0.3) !important; } @@ -22,7 +22,7 @@ button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS ._15ny::after, ._z-w, ._8i2, ._2nk0, ._2u4w, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .jx-result, ._2om3, ._2ol-, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._1gkq, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._3on6, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child, ._5fjv, ._5fjw, ._4z83 { border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; } -._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; } +._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; } ._4o58::after, .acw, .aclb, ._4qax, ._5h8f { border-color: rgba(255, 255, 255, 0.3) !important; } diff --git a/app/src/main/assets/css/themes/material_dark.compact.css b/app/src/main/assets/css/themes/material_dark.compact.css index 1b30aca8..860d01e5 100644 --- a/app/src/main/assets/css/themes/material_dark.compact.css +++ b/app/src/main/assets/css/themes/material_dark.compact.css @@ -10,9 +10,9 @@ body, #root, #header, [style*="background-color"], ._55wo, ._1upc, input, ._2f9r ._403n, ._1-kc { background: #898989 !important; } -button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(137, 137, 137, 0.2) !important; } +button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._2cpp, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(137, 137, 137, 0.2) !important; } -[style*="color"], body, input, ._42rv, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; } +[style*="color"], body, input, ._42rv, ._4qau, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; } ._15kl::before, ._5j35::after, ._2k4b, ._3to7, ._4nw8 { border-left: 1px solid rgba(255, 255, 255, 0.3) !important; } @@ -22,7 +22,7 @@ button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS ._15ny::after, ._z-w, ._8i2, ._2nk0, ._2u4w, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .jx-result, ._2om3, ._2ol-, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._1gkq, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._3on6, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child, ._5fjv, ._5fjw, ._4z83 { border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; } -._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; } +._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; } ._4o58::after, .acw, .aclb, ._4qax, ._5h8f { border-color: rgba(255, 255, 255, 0.3) !important; } diff --git a/app/src/main/assets/css/themes/material_glass.compact.css b/app/src/main/assets/css/themes/material_glass.compact.css index ff44628c..bd0f5671 100644 --- a/app/src/main/assets/css/themes/material_glass.compact.css +++ b/app/src/main/assets/css/themes/material_glass.compact.css @@ -10,9 +10,9 @@ body, #root, #header, [style*="background-color"], ._55wo, ._1upc, input, ._2f9r ._403n, ._1-kc { background: gray !important; } -button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(128, 128, 128, 0.05) !important; } +button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._2cpp, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(128, 128, 128, 0.05) !important; } -[style*="color"], body, input, ._42rv, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; } +[style*="color"], body, input, ._42rv, ._4qau, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; } ._15kl::before, ._5j35::after, ._2k4b, ._3to7, ._4nw8 { border-left: 1px solid rgba(255, 255, 255, 0.3) !important; } @@ -22,7 +22,7 @@ button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS ._15ny::after, ._z-w, ._8i2, ._2nk0, ._2u4w, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .jx-result, ._2om3, ._2ol-, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._1gkq, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._3on6, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child, ._5fjv, ._5fjw, ._4z83 { border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; } -._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; } +._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; } ._4o58::after, .acw, .aclb, ._4qax, ._5h8f { border-color: rgba(255, 255, 255, 0.3) !important; } diff --git a/app/src/main/assets/css/themes/material_light.compact.css b/app/src/main/assets/css/themes/material_light.compact.css index 0047a32b..f2b086a3 100644 --- a/app/src/main/assets/css/themes/material_light.compact.css +++ b/app/src/main/assets/css/themes/material_light.compact.css @@ -10,9 +10,9 @@ body, #root, #header, [style*="background-color"], ._55wo, ._1upc, input, ._2f9r ._403n, ._1-kc { background: white !important; } -button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(255, 255, 255, 0.2) !important; } +button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS, .touch::before, ._590n, ._4g8h, ._2cpp, ._5xo2, ._5u5a::before, ._4u3j, ._15ks, ._5hua, ._59tt, ._41ft, .jx-tokenizer, ._55fj, .excessItem, ._4e8n, ._5pxa._3uj9, ._5n_5, ._u2d, ._56bu::before, ._5h8f, ._d00, ._2066, ._2k51, ._4qax, .aclb, ._4756, ._w34, ._56bv::before, ._5769, ._34iv, ._z-w, .acbk { background: rgba(255, 255, 255, 0.2) !important; } -[style*="color"], body, input, ._42rv, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #000 !important; } +[style*="color"], body, input, ._42rv, ._4qau, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, .mentions-input, .mentions-placeholder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #000 !important; } ._15kl::before, ._5j35::after, ._2k4b, ._3to7, ._4nw8 { border-left: 1px solid rgba(0, 0, 0, 0.3) !important; } @@ -22,7 +22,7 @@ button:not([style*=image]), button::before, .touch ._56bt, ._56be::before, .btnS ._15ny::after, ._z-w, ._8i2, ._2nk0, ._2u4w, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .jx-result, ._2om3, ._2ol-, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._1gkq, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._3on6, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child, ._5fjv, ._5fjw, ._4z83 { border-bottom: 1px solid rgba(0, 0, 0, 0.3) !important; } -._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(0, 0, 0, 0.3) !important; } +._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(0, 0, 0, 0.3) !important; } ._4o58::after, .acw, .aclb, ._4qax, ._5h8f { border-color: rgba(0, 0, 0, 0.3) !important; } diff --git a/app/src/main/assets/js/notif_msg.js b/app/src/main/assets/js/notif_msg.js new file mode 100644 index 00000000..83405f39 --- /dev/null +++ b/app/src/main/assets/js/notif_msg.js @@ -0,0 +1,25 @@ +//binds callbacks to an invisible webview to take in the search events +if (!window.hasOwnProperty('frost_notif_msg')) { + console.log('Registering frost_notif_msg'); + window.frost_notif_msg = true; + var finished = false; + var x = new MutationObserver(function(mutations) { + var _f_thread = document.querySelector('#threadlist_rows'); + if (!_f_thread) return; + console.log('Found message threads', _f_thread.outerHTML); + if (typeof Frost !== 'undefined') Frost.handleHtml(_f_thread.outerHTML); + finished = true; + x.disconnect(); + }); + x.observe(document, { + childList: true, + subtree: true + }); + setTimeout(function() { + if (!finished) { + finished = true; + console.log('Message thread timeout cancellation') + if (typeof Frost !== 'undefined') Frost.handleHtml(""); + } + }, 20000); +} diff --git a/app/src/main/assets/js/notif_msg.min.js b/app/src/main/assets/js/notif_msg.min.js new file mode 100644 index 00000000..cb965d02 --- /dev/null +++ b/app/src/main/assets/js/notif_msg.min.js @@ -0,0 +1,17 @@ +if(!window.hasOwnProperty("frost_notif_msg")){ +console.log("Registering frost_notif_msg"), +window.frost_notif_msg=!0 +;var finished=!1,x=new MutationObserver(function(e){ +var o=document.querySelector("#threadlist_rows") +;o&&(console.log("Found message threads",o.outerHTML), +"undefined"!=typeof Frost&&Frost.handleHtml(o.outerHTML), +finished=!0,x.disconnect()) +}) +;x.observe(document,{ +childList:!0, +subtree:!0 +}),setTimeout(function(){ +finished||(finished=!0,console.log("Message thread timeout cancellation"), +"undefined"!=typeof Frost&&Frost.handleHtml("")) +},2e4) +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt index 12cb955d..c2b3cc0f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt @@ -1,7 +1,7 @@ package com.pitchedapps.frost import android.os.Bundle -import android.support.v7.app.AppCompatActivity +import ca.allanwang.kau.internal.KauBaseActivity import com.pitchedapps.frost.activities.LoginActivity import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.activities.SelectorActivity @@ -14,7 +14,7 @@ import com.pitchedapps.frost.utils.launchNewTask /** * Created by Allan Wang on 2017-05-28. */ -class StartActivity : AppCompatActivity() { +class StartActivity : KauBaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt index 80d2aa48..a1717de1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -1,8 +1,10 @@ package com.pitchedapps.frost.activities +import android.os.Bundle import android.support.constraint.ConstraintLayout import android.support.constraint.ConstraintSet import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView @@ -11,6 +13,8 @@ import ca.allanwang.kau.about.LibraryIItem import ca.allanwang.kau.adapters.FastItemThemedAdapter import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate +import ca.allanwang.kau.animators.FadeScaleAnimatorAdd +import ca.allanwang.kau.animators.KauAnimator import ca.allanwang.kau.utils.* import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.entity.Library @@ -23,6 +27,9 @@ import com.mikepenz.iconics.typeface.IIcon import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.Prefs +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread +import java.security.InvalidParameterException /** @@ -34,6 +41,8 @@ class AboutActivity : AboutActivityBase(null, { backgroundColor = Prefs.bgColor.withMinAlpha(200) cutoutForeground = if (0xff3b5998.toInt().isColorVisibleOn(Prefs.bgColor)) 0xff3b5998.toInt() else Prefs.accentColor cutoutDrawableRes = R.drawable.frost_f_256 + faqXmlRes = R.xml.frost_faq + faqParseNewLine = false }) { override fun getLibraries(libs: Libs): List { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt index 6806bf24..77a20d04 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt @@ -1,18 +1,16 @@ package com.pitchedapps.frost.activities -import android.content.Intent import android.os.Bundle -import android.support.v7.app.AppCompatActivity +import ca.allanwang.kau.internal.KauBaseActivity import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.materialDialogThemed import com.pitchedapps.frost.utils.setFrostTheme -import org.jetbrains.anko.contentView /** * Created by Allan Wang on 2017-06-12. */ -open class BaseActivity : AppCompatActivity() { +abstract class BaseActivity : KauBaseActivity() { override fun onBackPressed() { if (isTaskRoot && Prefs.exitConfirmation) { materialDialogThemed { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt index 2e4ae410..e419c21c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -10,14 +10,13 @@ import android.os.Bundle import android.os.Environment import android.support.design.widget.FloatingActionButton import android.support.v4.content.FileProvider -import android.support.v7.app.AppCompatActivity import android.view.View import android.view.ViewGroup import android.widget.ProgressBar import android.widget.TextView import ca.allanwang.kau.email.sendEmail +import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE -import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult import ca.allanwang.kau.permissions.kauRequestPermissions import ca.allanwang.kau.utils.* import com.bumptech.glide.Glide @@ -44,7 +43,7 @@ import java.util.* /** * Created by Allan Wang on 2017-07-15. */ -class ImageActivity : AppCompatActivity() { +class ImageActivity : KauBaseActivity() { val progress: ProgressBar by bindView(R.id.image_progress) val container: ViewGroup by bindView(R.id.image_container) @@ -230,11 +229,6 @@ class ImageActivity : AppCompatActivity() { deleteTempFile() super.onDestroy() } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - kauOnRequestPermissionsResult(permissions, grantResults) - } } internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconColor, val backgroundTint: Int = Prefs.iconBackgroundColor.withAlpha(255)) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt deleted file mode 100644 index f18d358e..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.pitchedapps.frost.activities - -import android.content.res.ColorStateList -import android.os.Bundle -import ca.allanwang.kau.imagepicker.ImagePickerActivityBase -import ca.allanwang.kau.imagepicker.ImagePickerActivityOverlayBase -import com.pitchedapps.frost.utils.Prefs - -/** - * Created by Allan Wang on 2017-07-23. - */ -class ImagePickerActivity : ImagePickerActivityOverlayBase() \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt index 28b8f466..2321a936 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt @@ -8,12 +8,12 @@ import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentPagerAdapter import android.support.v4.view.ViewPager -import android.support.v7.app.AppCompatActivity import android.view.View import android.view.WindowManager import android.widget.Button import android.widget.ImageButton import android.widget.ImageView +import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.ui.views.RippleCanvas import ca.allanwang.kau.ui.widgets.InkPageIndicator import ca.allanwang.kau.utils.* @@ -28,8 +28,11 @@ import org.jetbrains.anko.find /** * Created by Allan Wang on 2017-07-25. + * + * A beautiful intro activity + * Phone showcases are drawn via layers */ -class IntroActivity : AppCompatActivity(), ViewPager.PageTransformer, ViewPager.OnPageChangeListener { +class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.OnPageChangeListener { val ripple: RippleCanvas by bindView(R.id.intro_ripple) val viewpager: ViewPager by bindView(R.id.intro_viewpager) @@ -63,6 +66,7 @@ class IntroActivity : AppCompatActivity(), ViewPager.PageTransformer, ViewPager. if (barHasNext) viewpager.setCurrentItem(viewpager.currentItem + 1, true) else finish(next.x + next.pivotX, next.y + next.pivotY) } + skip.setOnClickListener { finish() } ripple.set(Prefs.bgColor) theme() } @@ -102,18 +106,19 @@ class IntroActivity : AppCompatActivity(), ViewPager.PageTransformer, ViewPager. ripple.ripple(blue, x, y, 600) { postDelayed(1000) { finish() } } - arrayOf(skip, indicator, next, fragments.last().view!!.find(R.id.intro_title), fragments.last().view!!.find(R.id.intro_desc)).forEach { - it.animate().alpha(0f).setDuration(600).start() + arrayOf(skip, indicator, next, fragments.last().view?.find(R.id.intro_title), fragments.last().view?.find(R.id.intro_desc)).forEach { + it?.animate()?.alpha(0f)?.setDuration(600)?.start() } if (Prefs.textColor != Color.WHITE) { - val f = fragments.last().view!!.find(R.id.intro_image).drawable - ValueAnimator.ofFloat(0f, 1f).apply { - addUpdateListener { - f.setTint(Prefs.textColor.blendWith(Color.WHITE, it.animatedValue as Float)) + val f = fragments.last().view?.find(R.id.intro_image)?.drawable + if (f != null) + ValueAnimator.ofFloat(0f, 1f).apply { + addUpdateListener { + f.setTint(Prefs.textColor.blendWith(Color.WHITE, it.animatedValue as Float)) + } + duration = 600 + start() } - duration = 600 - start() - } } if (Prefs.headerColor != blue) { ValueAnimator.ofFloat(0f, 1f).apply { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt index a6396b1b..df1228bd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -23,12 +23,11 @@ import android.view.Menu import android.view.MenuItem import android.webkit.ValueCallback import android.webkit.WebChromeClient -import ca.allanwang.kau.changelog.showChangelog -import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult import ca.allanwang.kau.searchview.SearchItem import ca.allanwang.kau.searchview.SearchView import ca.allanwang.kau.searchview.bindSearchView import ca.allanwang.kau.utils.* +import ca.allanwang.kau.xml.showChangelog import co.zsmb.materialdrawerkt.builders.Builder import co.zsmb.materialdrawerkt.builders.accountHeader import co.zsmb.materialdrawerkt.builders.drawer @@ -57,6 +56,7 @@ import com.pitchedapps.frost.fragments.WebFragment import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.utils.iab.FrostBilling import com.pitchedapps.frost.utils.iab.IABMain +import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import com.pitchedapps.frost.views.BadgedIcon import com.pitchedapps.frost.views.FrostViewPager import com.pitchedapps.frost.web.SearchWebView @@ -117,12 +117,11 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, Prefs.versionCode = BuildConfig.VERSION_CODE if (!BuildConfig.DEBUG) { showChangelog(R.xml.frost_changelog, Prefs.textColor) { theme() } - frostAnswersCustom("Version") { - putCustomAttribute("Version code", BuildConfig.VERSION_CODE) - putCustomAttribute("Version name", BuildConfig.VERSION_NAME) - putCustomAttribute("Build type", BuildConfig.BUILD_TYPE) - putCustomAttribute("Frost id", Prefs.frostId) - } + frostAnswersCustom("Version", + "Version code" to BuildConfig.VERSION_CODE, + "Version name" to BuildConfig.VERSION_NAME, + "Build type" to BuildConfig.BUILD_TYPE, + "Frost id" to Prefs.frostId) } } setContentView(R.layout.activity_main) @@ -388,6 +387,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, return true } + @SuppressLint("RestrictedApi") override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.action_settings -> { @@ -402,7 +402,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, } override fun openFileChooser(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) { - openImagePicker(filePathCallback, fileChooserParams) + openMediaPicker(filePathCallback, fileChooserParams) } @SuppressLint("NewApi") @@ -435,11 +435,6 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - kauOnRequestPermissionsResult(permissions, grantResults) - } - override fun onResume() { super.onResume() FbCookie.switchBackUser { } @@ -447,7 +442,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, override fun onStart() { //validate some pro features - if (!Prefs.pro) { + if (!IS_FROST_PRO) { if (Prefs.theme == Theme.CUSTOM.ordinal) Prefs.theme = Theme.DEFAULT.ordinal } super.onStart() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MediaPickerActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MediaPickerActivity.kt new file mode 100644 index 00000000..0d041e7a --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MediaPickerActivity.kt @@ -0,0 +1,10 @@ +package com.pitchedapps.frost.activities + +import ca.allanwang.kau.mediapicker.MediaPickerActivityOverlayBase +import ca.allanwang.kau.mediapicker.MediaType + +/** + * Created by Allan Wang on 2017-07-23. + */ +class ImagePickerActivity : MediaPickerActivityOverlayBase(MediaType.IMAGE) +class VideoPickerActivity : MediaPickerActivityOverlayBase(MediaType.VIDEO) \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt index 8455bf1e..7cbbe4df 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -1,18 +1,22 @@ package com.pitchedapps.frost.activities +import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem import ca.allanwang.kau.about.kauLaunchAbout -import ca.allanwang.kau.changelog.showChangelog import ca.allanwang.kau.kpref.activity.CoreAttributeContract import ca.allanwang.kau.kpref.activity.KPrefActivity import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import ca.allanwang.kau.kpref.activity.items.KPrefItemBase import ca.allanwang.kau.ui.views.RippleCanvas -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.finishSlideOut +import ca.allanwang.kau.utils.setMenuIcons +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.tint +import ca.allanwang.kau.xml.showChangelog import com.mikepenz.community_material_typeface_library.CommunityMaterial import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.pitchedapps.frost.BuildConfig @@ -75,13 +79,14 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() { } plainText(R.string.about_frost) { + descRes = R.string.about_frost_desc iicon = GoogleMaterial.Icon.gmd_info onClick = { _, _, _ -> kauLaunchAbout(AboutActivity::class.java); true } } plainText(R.string.replay_intro) { iicon = GoogleMaterial.Icon.gmd_replay - onClick = {_,_,_-> launchIntroActivity(cookies()); true} + onClick = { _, _, _ -> launchIntroActivity(cookies()); true } } if (BuildConfig.DEBUG) { @@ -98,6 +103,7 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() { setFrostResult(MainActivity.REQUEST_RESTART) } + @SuppressLint("MissingSuperCall") override fun onCreate(savedInstanceState: Bundle?) { setFrostTheme(true) super.onCreate(savedInstanceState) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt index 13d72ffe..7b612166 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt @@ -5,13 +5,12 @@ import android.net.Uri import android.os.Bundle import android.support.design.widget.CoordinatorLayout import android.support.design.widget.Snackbar -import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar import android.view.Menu import android.view.MenuItem import android.webkit.ValueCallback import android.webkit.WebChromeClient -import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult +import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.swipe.kauSwipeOnCreate import ca.allanwang.kau.swipe.kauSwipeOnDestroy import ca.allanwang.kau.swipe.kauSwipeOnPostCreate @@ -31,7 +30,7 @@ import com.pitchedapps.frost.web.FrostWebView /** * Created by Allan Wang on 2017-06-01. */ -open class WebOverlayActivity : AppCompatActivity(), +open class WebOverlayActivity : KauBaseActivity(), ActivityWebContract, FileChooserContract by FileChooserDelegate() { val toolbar: Toolbar by bindView(R.id.overlay_toolbar) @@ -126,18 +125,13 @@ open class WebOverlayActivity : AppCompatActivity(), } override fun openFileChooser(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) { - openImagePicker(filePathCallback, fileChooserParams) + openMediaPicker(filePathCallback, fileChooserParams) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (onActivityResultWeb(requestCode, resultCode, data)) return } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - kauOnRequestPermissionsResult(permissions, grantResults) - } - override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_web, menu) toolbar.tint(Prefs.iconColor) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt b/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt index bd31d6ce..fd8a3677 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt @@ -5,16 +5,18 @@ import android.content.Intent import android.net.Uri import android.webkit.ValueCallback import android.webkit.WebChromeClient -import ca.allanwang.kau.imagepicker.kauLaunchImagePicker -import ca.allanwang.kau.imagepicker.kauOnImagePickerResult +import ca.allanwang.kau.mediapicker.MediaPickerActivityOverlayBase +import ca.allanwang.kau.mediapicker.MediaType +import ca.allanwang.kau.mediapicker.kauLaunchMediaPicker +import ca.allanwang.kau.mediapicker.kauOnMediaPickerResult import com.pitchedapps.frost.activities.ImagePickerActivity +import com.pitchedapps.frost.activities.VideoPickerActivity import com.pitchedapps.frost.utils.L -import java.io.File /** * Created by Allan Wang on 2017-07-04. */ -const val IMAGE_CHOOSER_REQUEST = 67 +const val MEDIA_CHOOSER_RESULT = 67 interface FileChooserActivityContract { fun openFileChooser(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) @@ -22,7 +24,7 @@ interface FileChooserActivityContract { interface FileChooserContract { var filePathCallback: ValueCallback>? - fun Activity.openImagePicker(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) + fun Activity.openMediaPicker(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) fun Activity.onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean } @@ -30,16 +32,17 @@ class FileChooserDelegate : FileChooserContract { override var filePathCallback: ValueCallback>? = null - override fun Activity.openImagePicker(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) { + override fun Activity.openMediaPicker(filePathCallback: ValueCallback>, fileChooserParams: WebChromeClient.FileChooserParams) { this@FileChooserDelegate.filePathCallback = filePathCallback - kauLaunchImagePicker(ImagePickerActivity::class.java, IMAGE_CHOOSER_REQUEST) + val isVideo = fileChooserParams.acceptTypes.firstOrNull() == "video/*" + kauLaunchMediaPicker(if (isVideo) VideoPickerActivity::class.java else ImagePickerActivity::class.java, MEDIA_CHOOSER_RESULT) } override fun Activity.onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean { L.d("FileChooser On activity results web $requestCode") - if (requestCode != IMAGE_CHOOSER_REQUEST) return false - val results = kauOnImagePickerResult(resultCode, intent).map { it.uri }.toTypedArray() - L.d("FileChooser result ${results.contentToString()}") + if (requestCode != MEDIA_CHOOSER_RESULT) return false + val results = kauOnMediaPickerResult(resultCode, intent).map { it.uri }.toTypedArray() + L.i("FileChooser result ${results.contentToString()}") //proper path content://com.android.providers.media.documents/document/image%3A36341 L.d("FileChooser Callback received; ${filePathCallback != null}") filePathCallback?.onReceiveValue(results) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt index 622be067..7cd93d14 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt @@ -1,5 +1,7 @@ package com.pitchedapps.frost.facebook +import com.pitchedapps.frost.utils.L + /** * Created by Allan Wang on 2017-07-07. * @@ -13,22 +15,27 @@ class FbUrlFormatter(url: String) { val cleaned: String init { - var cleanedUrl = url - discardable.forEach { cleanedUrl = cleanedUrl.replace(it, "", true) } - val changed = cleanedUrl != url //note that discardables strip away the first ? - decoder.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } - val qm = cleanedUrl.indexOf(if (changed) "&" else "?") - if (qm > -1) { - cleanedUrl.substring(qm + 1).split("&").forEach { - val p = it.split("=") - queries.put(p[0], p.elementAtOrNull(1) ?: "") + if (url.isNullOrBlank()) cleaned = "" + else { + var cleanedUrl = url + discardable.forEach { cleanedUrl = cleanedUrl.replace(it, "", true) } + val changed = cleanedUrl != url //note that discardables strip away the first ? + decoder.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } + val qm = cleanedUrl.indexOf(if (changed) "&" else "?") + if (qm > -1) { + cleanedUrl.substring(qm + 1).split("&").forEach { + val p = it.split("=") + queries.put(p[0], p.elementAtOrNull(1) ?: "") + } + cleanedUrl = cleanedUrl.substring(0, qm) } - cleanedUrl = cleanedUrl.substring(0, qm) + discardableQueries.forEach { queries.remove(it) } + if (cleanedUrl.startsWith("#!/")) cleanedUrl = cleanedUrl.substring(2) + if (cleanedUrl.startsWith("/")) cleanedUrl = FB_URL_BASE + cleanedUrl.substring(1) + cleanedUrl = cleanedUrl.replaceFirst(".facebook.com//", ".facebook.com/") //sometimes we are given a bad url + L.v("Formatted url from $url to $cleanedUrl") + cleaned = cleanedUrl } - discardableQueries.forEach { queries.remove(it) } - if (cleanedUrl.startsWith("#!/")) cleanedUrl = cleanedUrl.substring(2) - if (cleanedUrl.startsWith("/")) cleanedUrl = FB_URL_BASE + cleanedUrl.substring(1) - cleaned = cleanedUrl } override fun toString(): String { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt index ac979c85..0992a9cb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt @@ -3,7 +3,6 @@ package com.pitchedapps.frost.injectors import android.graphics.Color import android.webkit.WebView import ca.allanwang.kau.utils.* -import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs /** diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt index de270948..fae1846b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt @@ -15,7 +15,9 @@ enum class JsActions(body: String) : InjectorContract { */ LOGIN_CHECK("document.getElementById('signup-button')&&Frost.loadLogin();"), BASE_HREF("document.write(\"\");"), - GET_MESSAGES("setTimeout(function(){Frost.handleHtml(document.getElementById('threadlist_rows').outerHtml)},1000)"), + /** + * Used as a pseudoinjector for maybe functions + */ EMPTY(""); val function = "!function(){$body}();" diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt index b22abd70..d2201c52 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt @@ -8,7 +8,7 @@ import android.webkit.WebView * The enum name must match the css file name */ enum class JsAssets : InjectorContract { - MENU, CLICK_A, CONTEXT_A, HEADER_BADGES, SEARCH, TEXTAREA_LISTENER + MENU, CLICK_A, CONTEXT_A, HEADER_BADGES, SEARCH, TEXTAREA_LISTENER, NOTIF_MSG ; var file = "${name.toLowerCase()}.min.js" diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index 05497904..3ddad869 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -14,10 +14,13 @@ import com.pitchedapps.frost.dbflow.loadFbCookiesSync import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.USER_AGENT_BASIC +import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.frostAnswersCustom +import com.pitchedapps.frost.web.MessageWebView import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread import org.jsoup.Jsoup import org.jsoup.nodes.Element import java.util.concurrent.Future @@ -32,6 +35,8 @@ class NotificationService : JobService() { var future: Future? = null + val startTime = System.currentTimeMillis() + companion object { val epochMatcher: Regex by lazy { Regex(":([0-9]*?),") } val notifIdMatcher: Regex by lazy { Regex("notif_id\":([0-9]*?),") } @@ -40,38 +45,47 @@ class NotificationService : JobService() { } override fun onStopJob(params: JobParameters?): Boolean { + val time = System.currentTimeMillis() - startTime + L.d("Notification service has finished abruptly in $time ms") + frostAnswersCustom("NotificationTime", + "Type" to "Service force stop", + "IM Included" to Prefs.notificationsInstantMessages, + "Duration" to time) future?.cancel(true) future = null return false } + fun finish(params: JobParameters?) { + val time = System.currentTimeMillis() - startTime + L.d("Notification service has finished in $time ms") + frostAnswersCustom("NotificationTime", + "Type" to "Service", + "IM Included" to Prefs.notificationsInstantMessages, + "Duration" to time) + jobFinished(params, false) + future?.cancel(true) + future = null + } + override fun onStartJob(params: JobParameters?): Boolean { future = doAsync { if (Prefs.notificationAllAccounts) { val cookies = loadFbCookiesSync() cookies.forEach { fetchGeneralNotifications(it) } -// if (Prefs.notificationsInstantMessages) { -// Prefs.prevId = Prefs.userId -// uiThread { -// val messageWebView = MessageWebView(this@NotificationService, params) -// cookies.forEach { messageWebView.request(it) } -// } -// return@doAsync -// } } else { val currentCookie = loadFbCookie(Prefs.userId) if (currentCookie != null) { fetchGeneralNotifications(currentCookie) -// if (Prefs.notificationsInstantMessages) { -// uiThread { MessageWebView(this@NotificationService, params).request(currentCookie) } -// return@doAsync -// } } } - L.d("Finished notifications") - jobFinished(params, false) - future = null + L.d("Finished main notifications") + if (Prefs.notificationsInstantMessages) { + val currentCookie = loadFbCookie(Prefs.userId) + if (currentCookie != null) + uiThread { MessageWebView(this@NotificationService, params, currentCookie) } + } else finish(params) } return true } @@ -104,10 +118,7 @@ class NotificationService : JobService() { } if (newLatestEpoch != prevLatestEpoch) prevNotifTime.copy(epoch = newLatestEpoch).save() L.d("Notif new latest epoch ${lastNotificationTime(data.id).epoch}") - frostAnswersCustom("Notifications") { - putCustomAttribute("Type", "General") - putCustomAttribute("Count", notifCount) - } + frostAnswersCustom("Notifications", "Type" to "General", "Count" to notifCount) summaryNotification(data.id, notifCount) } @@ -132,12 +143,6 @@ class NotificationService : JobService() { val doc = Jsoup.parseBodyFragment(content) val unreadNotifications = (doc.getElementById("threadlist_rows") ?: return L.eThrow("Notification messages not found")).getElementsByClass("aclb") var notifCount = 0 - L.d("IM notif count ${unreadNotifications.size}") - unreadNotifications.forEach { - with(it) { - L.d("notif ${id()} ${className()}") - } - } val prevNotifTime = lastNotificationTime(data.id) val prevLatestEpoch = prevNotifTime.epochIm L.v("Notif Prev Latest Im Epoch $prevLatestEpoch") @@ -154,10 +159,7 @@ class NotificationService : JobService() { } if (newLatestEpoch != prevLatestEpoch) prevNotifTime.copy(epochIm = newLatestEpoch).save() L.d("Notif new latest im epoch ${lastNotificationTime(data.id).epochIm}") - frostAnswersCustom("Notifications") { - putCustomAttribute("Type", "Message") - putCustomAttribute("Count", notifCount) - } + frostAnswersCustom("Notifications", "Type" to "Message", "Count" to notifCount) summaryNotification(data.id, notifCount) } @@ -173,7 +175,8 @@ class NotificationService : JobService() { //fetch convo pic val p = element.select("i.img[style*=url]") val pUrl = profMatcher.find(p.attr("style"))?.groups?.get(1)?.value ?: "" - return NotificationContent(data, notifId.toInt(), a.attr("href"), a.text(), text, epoch, pUrl) + L.v("url ${a.attr("href")}") + return NotificationContent(data, notifId.toInt(), a.attr("href"), a.text(), text, epoch, pUrl.formattedFbUrl) } private fun Context.debugNotification(text: String) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt index 9c9754bb..e37afc33 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt @@ -41,7 +41,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { setFrostTheme(true) themeExterior() invalidateOptionsMenu() - frostAnswersCustom("Theme") { putCustomAttribute("Count", text.toString()) } + frostAnswersCustom("Theme", "Count" to text) } true } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt index 05a852ee..594cbe01 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt @@ -22,7 +22,9 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = { // Experimental content starts here ------------------ - + checkbox(R.string.notification_messages, { Prefs.notificationsInstantMessages }, { Prefs.notificationsInstantMessages = it }) { + descRes = R.string.notification_messages_desc + } // Experimental content ends here -------------------- diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt index a20e755f..b053b9dd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -97,7 +97,8 @@ object Prefs : KPref() { var notificationAllAccounts: Boolean by kpref("notification_all_accounts", true) - var notificationsInstantMessages: Boolean by kpref("notification_im", true) + //todo remove from experimental once stabilized + var notificationsInstantMessages: Boolean by kpref("notification_im", Showcase.experimentalDefault) var notificationVibrate: Boolean by kpref("notification_vibrate", true) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt index 40e16f20..cc3ea52e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -116,9 +116,14 @@ fun frostAnswers(action: Answers.() -> Unit) { Answers.getInstance().action() } -fun frostAnswersCustom(name: String, action: CustomEvent.() -> Unit = {}) { +fun frostAnswersCustom(name: String, vararg events: Pair) { frostAnswers { - logCustom(CustomEvent("Frost $name").apply { action() }) + logCustom(CustomEvent("Frost $name").apply { + events.forEach { (key, value) -> + if (value is Number) putCustomAttribute(key, value) + else putCustomAttribute(key, value.toString()) + } + }) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt index ea66030f..3918a993 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt @@ -41,6 +41,7 @@ class WebContext(val unformattedUrl: String, val text: String?) { } enum class WebContextType(val textId: Int, val onClick: (c: Context, wc: WebContext) -> Unit) { + OPEN_LINK(R.string.open_link, { c, wc -> c.launchWebOverlay(wc.unformattedUrl) }), COPY_LINK(R.string.copy_link, { c, wc -> c.copyToClipboard(wc.url) }), COPY_TEXT(R.string.copy_text, { c, wc -> if (wc.text != null) c.copyToClipboard(wc.text) else c.toast(R.string.no_text) }), SHARE_LINK(R.string.share_link, { c, wc -> c.shareText(wc.url) }), diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt index b3992ff4..bad7f8fd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt @@ -15,6 +15,10 @@ import com.pitchedapps.frost.utils.frostAnswers */ private const val FROST_PRO = "frost_pro" +/** + * Implemented pro checker with a hook for debug builds + * Use this when checking if the pro feature is enabled + */ val IS_FROST_PRO: Boolean get() = (BuildConfig.DEBUG && Prefs.debugPro) || Prefs.pro diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt index df468715..8ae54ef3 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt @@ -1,8 +1,6 @@ package com.pitchedapps.frost.views import android.content.Context -import android.graphics.Color -import android.graphics.drawable.ColorDrawable import android.graphics.drawable.GradientDrawable import android.support.constraint.ConstraintLayout import android.util.AttributeSet diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt index b8ba0d1d..343674d5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt @@ -1,10 +1,9 @@ package com.pitchedapps.frost.web import android.net.Uri -import android.webkit.ConsoleMessage -import android.webkit.ValueCallback -import android.webkit.WebChromeClient -import android.webkit.WebView +import android.webkit.* +import ca.allanwang.kau.permissions.PERMISSION_ACCESS_FINE_LOCATION +import ca.allanwang.kau.permissions.kauRequestPermissions import ca.allanwang.kau.utils.snackbar import com.pitchedapps.frost.contracts.ActivityWebContract import com.pitchedapps.frost.utils.L @@ -33,6 +32,7 @@ class FrostChromeClient(webCore: FrostWebViewCore) : WebChromeClient() { val progressObservable: Subject = webCore.progressObservable val titleObservable: BehaviorSubject = webCore.titleObservable val activityContract = (webCore.context as? ActivityWebContract) + val context = webCore.context!! companion object { val consoleBlacklist = setOf( @@ -62,4 +62,12 @@ class FrostChromeClient(webCore: FrostWebViewCore) : WebChromeClient() { return activityContract != null } + override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) { + L.d("Requesting geolocation") + context.kauRequestPermissions(PERMISSION_ACCESS_FINE_LOCATION) { + granted, _ -> + L.d("Geolocation response received; ${if (granted) "granted" else "denied"}") + callback(origin, granted, true) + } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt index 6ec1aec5..1679d7a3 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt @@ -16,6 +16,7 @@ import ca.allanwang.kau.utils.withAlpha import com.pitchedapps.frost.R import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.USER_AGENT_BASIC +import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import io.reactivex.android.schedulers.AndroidSchedulers @@ -61,7 +62,7 @@ class FrostWebView @JvmOverloads constructor( baseEnum = enum with(settings) { javaScriptEnabled = true - if (url.contains("com/message")) + if (url.contains("/message")) userAgentString = USER_AGENT_BASIC allowFileAccess = true textZoom = Prefs.webTextScaling diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt index cb5125c4..9f7dd916 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -1,6 +1,5 @@ package com.pitchedapps.frost.web -import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.graphics.Bitmap @@ -17,6 +16,7 @@ import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.injectors.* import com.pitchedapps.frost.utils.* +import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import io.reactivex.subjects.Subject /** @@ -71,8 +71,8 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient } view.jsInject( CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons), - CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && Prefs.pro), - CssHider.ADS.maybe(!Prefs.showFacebookAds && Prefs.pro) + CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && IS_FROST_PRO), + CssHider.ADS.maybe(!Prefs.showFacebookAds && IS_FROST_PRO) ) onPageFinishedActions(url) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/MessageWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/MessageWebView.kt index 0f3a12b6..53fa0657 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/MessageWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/MessageWebView.kt @@ -6,23 +6,24 @@ import android.webkit.JavascriptInterface import android.webkit.WebView import ca.allanwang.kau.utils.gone import com.pitchedapps.frost.dbflow.CookieModel -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.USER_AGENT_BASIC -import com.pitchedapps.frost.injectors.JsActions +import com.pitchedapps.frost.injectors.JsAssets import com.pitchedapps.frost.services.NotificationService import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.frostAnswersCustom import org.jetbrains.anko.doAsync -import org.jetbrains.anko.runOnUiThread -@SuppressLint("ViewConstructor") /** * Created by Allan Wang on 2017-07-17. * * Bare boned headless view made solely to extract conversation info */ -class MessageWebView(val service: NotificationService, val params: JobParameters?) : WebView(service) { +@SuppressLint("ViewConstructor") +class MessageWebView(val service: NotificationService, val params: JobParameters?, val cookie: CookieModel) : WebView(service) { + + private val startTime = System.currentTimeMillis() + private var isCancelled = false init { gone() @@ -33,48 +34,33 @@ class MessageWebView(val service: NotificationService, val params: JobParameters private fun setupWebview() { settings.javaScriptEnabled = true settings.userAgentString = USER_AGENT_BASIC - webViewClient = HeadlessWebViewClient("MessageNotifs", JsActions.GET_MESSAGES) + webViewClient = HeadlessWebViewClient("MessageNotifs", JsAssets.NOTIF_MSG) webChromeClient = QuietChromeClient() addJavascriptInterface(MessageJSI(), "Frost") + loadUrl(FbTab.MESSAGES.url) } - private val startTime = System.currentTimeMillis() - private val endTime: Long by lazy { System.currentTimeMillis() } - private var inProgress = false - private val pendingRequests: MutableList = mutableListOf() - private lateinit var data: CookieModel - - fun request(data: CookieModel) { - pendingRequests.add(data) - if (inProgress) return - inProgress = true - load(data) + fun finish() { + if (isCancelled) return + isCancelled = true + post { destroy() } + service.finish(params) } - private fun load(data: CookieModel) { - L.d("Notif retrieving messages", data.toString()) - this.data = data - FbCookie.setWebCookie(data.cookie) { context.runOnUiThread { L.d("Notif messages load"); loadUrl(FbTab.MESSAGES.url) } } + override fun destroy() { + L.d("MessageWebView destroyed") + super.destroy() } inner class MessageJSI { @JavascriptInterface fun handleHtml(html: String) { - L.d("Notif messages received", data.toString()) - doAsync { service.fetchMessageNotifications(data, html) } - pendingRequests.remove(data) - if (pendingRequests.isEmpty()) { - val time = endTime - startTime - L.d("Notif messages finished $time") - frostAnswersCustom("Notifications") { - putCustomAttribute("Message retrieval duration", time) - } - post { destroy() } - service.jobFinished(params, false) - service.future = null - } else { - load(pendingRequests.first()) - } + if (isCancelled) return + if (html.length < 10) return finish() + val time = System.currentTimeMillis() - startTime + L.d("Notif messages fetched in $time ms") + frostAnswersCustom("NotificationTime", "Type" to "IM Headless", "Duration" to time) + doAsync { service.fetchMessageNotifications(cookie, html); finish() } } } diff --git a/app/src/main/play/en-CA/listing/fulldescription b/app/src/main/play/en-CA/listing/fulldescription index 32cf0503..16b0e8f7 100644 --- a/app/src/main/play/en-CA/listing/fulldescription +++ b/app/src/main/play/en-CA/listing/fulldescription @@ -8,13 +8,18 @@ While being a web wrapper, Frost contains many unique and native features such a • Complete theme engine - Frost contains very comprehensive themes that customize all components of the app. Frost is also the only app to support transparent themes. • Fully opened - Nothing speaks for privacy more than being open sourced. Frost is proud to be one of those apps, and can be found on github (Link in the app's about section) -Permissions used and why: +Mandatory permissions used and why: • Internet, Network State, Wifi State - Frost fetches the pages from Facebook's mobile website. It also needs the network state so as to limit internet usage when you are on a metered network. • Receive Boot Completed - Frost notifications persist on reboot, and need this permission to be added each time. -• Read/write external storage - Needed to upload photos in a new status and save photos when prompted • Vibrate - Needed to vibrate phone for notifications; this can be toggled in the settings • Billing - For purchasing pro and unlocking all of Frost's features + +Optional permissions used and why: +(these are only requested when they have to be, and are disabled until then) +• Read/write external storage - Needed to upload photos in a new status and save photos when prompted +• Fine/coarse location - Needed for the check in option if users wish to search for their location + • That's it! No privacy intrusion and no extra demands. Permissions NOT used and why: diff --git a/app/src/main/res/layout/intro_end.xml b/app/src/main/res/layout/intro_end.xml index 10132546..67931e43 100644 --- a/app/src/main/res/layout/intro_end.xml +++ b/app/src/main/res/layout/intro_end.xml @@ -12,7 +12,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/intro_end" - app:layout_constraintBottom_toTopOf="@+id/intro_image" + app:layout_constraintBottom_toTopOf="@id/intro_image" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e6dc5b24..4c685908 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,8 +1,5 @@ - @color/facebook_blue - @color/facebook_blue_dark - #FF4081 @color/facebook_blue #3b5998 #2e4b86 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 92ab2491..d4a7c9dc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,9 +1,6 @@ pitchedapps@gmail.com com.pitchedapps.frost - About Frost for Facebook - Frost is a fully themable, fully functional alternative to the official Facebook app, made from scratch and proudly open sourced. - Hello World from section: %1$d Feed Most Recent @@ -46,6 +43,7 @@ Frost for Facebook: Link Debug Write here. Note that your link may contain private information, but I won\'t be able to see it as the post isn\'t public. The url will still help with debugging though. If a link isn\'t loading properly, you can email me so I can help debug it. Clicking okay will open an email request + Open Link Copy Link Copy Text Frost for Facebook: Image Link Debug diff --git a/app/src/main/res/values/strings_about.xml b/app/src/main/res/values/strings_about.xml new file mode 100644 index 00000000..68590718 --- /dev/null +++ b/app/src/main/res/values/strings_about.xml @@ -0,0 +1,23 @@ + + + + Frost is a fully themable, + fully functional alternative to the official Facebook app, made from scratch and proudly open sourced. + + Frost FAQ + + Can you add feature xxx? + I\'m always opened to suggestions, + and if a feature will enhance your experience, I\'d like to hear it. + However, please consider taking a look at my + issue tracker + + I can\'t scroll horizontally in the webviews. + This is known since the viewpager takes priority for horizontal scrolling. + Frost has addressed this by allowing horizontal web scrolls if you tap and hold before scrolling. + + Can I get more frequent notifications? + I made the decision to prioritize battery life by using a newer job scheduler for Android. + This means that your framework picks the best time to fetch the notifications, and the lowest window is 15 minutes. + This is also why I don\'t require the wakelock permission + \ No newline at end of file diff --git a/app/src/main/res/values/strings_pref_notifications.xml b/app/src/main/res/values/strings_pref_notifications.xml index 1d605c2b..00c30b57 100644 --- a/app/src/main/res/values/strings_pref_notifications.xml +++ b/app/src/main/res/values/strings_pref_notifications.xml @@ -9,6 +9,8 @@ Empty Keyword Notify from all accounts Get notifications for every account that is logged in. Disabling this will only fetch notifications form the currently selected account. + Enable message notifications + Get instant message notifications for your current account. Fetch Notifications Now Trigger the notification fetcher one time. Fetching Notifications… diff --git a/app/src/main/res/values/strings_preferences b/app/src/main/res/values/strings_preferences deleted file mode 100644 index 1108d08d..00000000 --- a/app/src/main/res/values/strings_preferences +++ /dev/null @@ -1,20 +0,0 @@ - - Appearance - Theme, Items to display, etc - - Frequency, filters, etc - - News Feed - Define what items appear in the newsfeed - - Behaviour - Define how the app interacts in certain settings - - Experimental - Enable early access to potentially unstable features - - Get Frost Pro - Purchase or restore pro and unlock the full potential of Frost! Includes ad blockers, custom themes, full configurations, and much more to come! - - Replay Introduction - \ No newline at end of file diff --git a/app/src/main/res/values/strings_preferences.xml b/app/src/main/res/values/strings_preferences.xml new file mode 100644 index 00000000..c2ba0b36 --- /dev/null +++ b/app/src/main/res/values/strings_preferences.xml @@ -0,0 +1,24 @@ + + Appearance + Theme, Items to display, etc + + Frequency, filters, etc + + News Feed + Define what items appear in the newsfeed + + Behaviour + Define how the app interacts in certain settings + + Experimental + Enable early access to potentially unstable features + + Get Frost Pro + Purchase or restore pro and unlock the full potential of Frost! Includes ad blockers, custom themes, full configurations, and much more to come! + + About Frost for Facebook + Version, Credits, and FAQs + + + Replay Introduction + \ No newline at end of file diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml index 4b41553b..8f68de9f 100644 --- a/app/src/main/res/xml/frost_changelog.xml +++ b/app/src/main/res/xml/frost_changelog.xml @@ -10,14 +10,19 @@ - + + + + + + + + + - - - diff --git a/app/src/main/res/xml/frost_faq.xml b/app/src/main/res/xml/frost_faq.xml new file mode 100644 index 00000000..e46d2d50 --- /dev/null +++ b/app/src/main/res/xml/frost_faq.xml @@ -0,0 +1,17 @@ + + + + issue tracker first to avoid duplicate requests.]]> + + + + + + + \ No newline at end of file diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt index 080132bd..950be495 100644 --- a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt +++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt @@ -1,6 +1,5 @@ package com.pitchedapps.frost.facebook -import okhttp3.HttpUrl import org.junit.Test import kotlin.test.assertEquals @@ -15,29 +14,30 @@ class FbUrlTest { assertEquals(expected, fbUrl.toString(), "FbUrl Mismatch:\n${fbUrl.toLogList().joinToString("\n\t")}") } - @Test - fun base() { + @Test fun base() { val url = "https://touch.facebook.com/relative/?asdf=1234&hjkl=7890" assertFbFormat(url, url) } - @Test - fun relative() { + @Test fun relative() { val url = "/relative/?asdf=1234&hjkl=7890" assertFbFormat("$FB_URL_BASE${url.substring(1)}", url) } - @Test - fun redirect() { - assertFbFormat("$FB_URL_BASE/relative/?asdf=1234&hjkl=7890", "https://touch.facebook.com/l.php?u=$FB_URL_BASE/relative/&asdf=1234&hjkl=7890") + @Test fun redirect() { + assertFbFormat("${FB_URL_BASE}relative/?asdf=1234&hjkl=7890", "https://touch.facebook.com/l.php?u=${FB_URL_BASE}relative/&asdf=1234&hjkl=7890") } @Test fun discard() { - val prefix = "$FB_URL_BASE/?test=1234" + val prefix = "$FB_URL_BASE?test=1234" val suffix = "&apple=notorange" assertFbFormat("$prefix$suffix", "$prefix&ref=hello$suffix") } + @Test fun doubleDash() { + assertFbFormat("${FB_URL_BASE}relative", "$FB_URL_BASE/relative") + } + @Test fun css() { val expected = "https://test.com?efg=hi&oh=bye&oe=apple" val orig = "https\\3a //test.com?efg\\3d hi\\26 oh\\3d bye\\26 oe\\3d apple" diff --git a/build.gradle b/build.gradle index db334854..dd400eac 100644 --- a/build.gradle +++ b/build.gradle @@ -2,12 +2,12 @@ buildscript { repositories { + google() jcenter() - mavenCentral() maven { url 'https://maven.fabric.io/public' } } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0-alpha9' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${KOTLIN}" classpath 'io.fabric.tools:gradle:1.+' classpath 'com.github.triplet.gradle:play-publisher:1.2.0' diff --git a/docs/Changelog.md b/docs/Changelog.md index 5d5ed08c..c4abb9ae 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,5 +1,17 @@ # Changelog +## v1.4.2 +* Experimental: Add notifications for messages; report to me if this drains your battery +* Add FAQ in the about section +* Add video uploading +* Add open link option in context menu + +## v1.4.1 +* Add intro pages +* Style new comment highlights +* Style reaction background +* Disable pull to refresh when typing is detected + ## v1.4 * Update IAB helper * Create image viewing and downloading; long press any image! diff --git a/gradle.properties b/gradle.properties index 48998995..589a03a0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,19 +17,18 @@ MIN_SDK=21 TARGET_SDK=26 BUILD_TOOLS=26.0.1 -KAU=bbaa795 +KAU=ca2cda0 KOTLIN=1.1.3-2 CRASHLYTICS=2.6.8 DBFLOW=4.0.5 -IAB=1.0.42 +IAB=1.0.43 IICON_COMMUNITY=1.9.32.2 IICON_MATERIAL=2.2.0.3 JSOUP=1.10.3 LEAK_CANARY=1.5.1 -MATERIAL_DRAWER=5.9.4 -MATERIAL_DRAWER_KT=1.0.5 +MATERIAL_DRAWER_KT=1.0.6 OKHTTP=3.8.1 PAPER_PARCEL=2.0.1 -ROBOELECTRIC=3.4-rc3 +ROBOELECTRIC=3.4 SCALE_IMAGE_VIEW=3.6.0 SLIDING_PANEL=3.3.1 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa82d1ab..f5fba018 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun May 28 21:23:49 PDT 2017 +#Tue Aug 01 10:58:12 PDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip -- cgit v1.2.3