├── .github
└── FUNDING.yml
├── .gitignore
├── .gitmodules
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── release
│ ├── output-metadata.json
│ └── output.json
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-web.png
│ ├── java
│ ├── com
│ │ └── google
│ │ │ └── android
│ │ │ ├── a
│ │ │ ├── LauncherOverlayBinder.java
│ │ │ ├── a.java
│ │ │ └── c.java
│ │ │ ├── apps
│ │ │ └── gsa
│ │ │ │ └── nowoverlayservice
│ │ │ │ └── ConfigurationOverlayController.kt
│ │ │ └── libraries
│ │ │ ├── gsa
│ │ │ └── d
│ │ │ │ └── a
│ │ │ │ ├── BaseCallback.java
│ │ │ │ ├── ByteBundleHolder.java
│ │ │ │ ├── DialogListeners.java
│ │ │ │ ├── DialogOverlayController.java
│ │ │ │ ├── MinusOneOverlayCallback.java
│ │ │ │ ├── OverlayController.java
│ │ │ │ ├── OverlayControllerBinder.java
│ │ │ │ ├── OverlayControllerCallback.java
│ │ │ │ ├── OverlayControllerLayoutChangeListener.java
│ │ │ │ ├── OverlayControllerSlidingPanelLayout.java
│ │ │ │ ├── OverlayControllerStateChanger.java
│ │ │ │ ├── OverlaysController.java
│ │ │ │ ├── PanelState.java
│ │ │ │ ├── SlidingPanelLayout.java
│ │ │ │ ├── SlidingPanelLayoutInterpolator.java
│ │ │ │ ├── SlidingPanelLayoutProperty.java
│ │ │ │ ├── TransparentOverlayController.java
│ │ │ │ ├── t.java
│ │ │ │ └── v.java
│ │ │ └── i
│ │ │ ├── LauncherOverlayInterfaceBinder.java
│ │ │ ├── a.java
│ │ │ ├── d.java
│ │ │ └── f.java
│ └── ua
│ │ └── itaysonlab
│ │ ├── homefeeder
│ │ ├── HFApplication.kt
│ │ ├── activites
│ │ │ └── MainActivity.kt
│ │ ├── fragments
│ │ │ ├── AboutFragment.kt
│ │ │ ├── PluginsFragment.kt
│ │ │ ├── PreferenceFragment.kt
│ │ │ └── base
│ │ │ │ └── FixedPreferencesFragment.kt
│ │ ├── kt
│ │ │ └── KtExtensions.kt
│ │ ├── overlay
│ │ │ ├── DrawerOverlayService.kt
│ │ │ ├── OverlayKt.kt
│ │ │ ├── feed
│ │ │ │ ├── FeedAdapter.kt
│ │ │ │ └── binders
│ │ │ │ │ ├── FeedBinder.kt
│ │ │ │ │ ├── StoryCardBinder.kt
│ │ │ │ │ ├── TextCardBinder.kt
│ │ │ │ │ └── TextCardWithActionsBinder.kt
│ │ │ ├── launcherapi
│ │ │ │ ├── LauncherAPI.kt
│ │ │ │ └── OverlayThemeHolder.kt
│ │ │ └── rvutils
│ │ │ │ └── StackBlur.java
│ │ ├── pluginsystem
│ │ │ ├── PluginConnector.kt
│ │ │ └── PluginFetcher.kt
│ │ ├── preferences
│ │ │ ├── HFPluginPreferences.kt
│ │ │ └── HFPreferences.kt
│ │ ├── prefui
│ │ │ └── HFElementPreview.kt
│ │ ├── theming
│ │ │ └── Theming.kt
│ │ └── utils
│ │ │ ├── Logger.kt
│ │ │ ├── OverlayBridge.kt
│ │ │ ├── PreferenceHelper.kt
│ │ │ └── RelativeTimeHelper.kt
│ │ └── replica
│ │ └── vkpopup
│ │ ├── ActionAdapter.kt
│ │ ├── ActionDivider.kt
│ │ ├── ActionStyle.kt
│ │ ├── ActionVh.kt
│ │ ├── DialogActionsVcByPopup.kt
│ │ ├── DividerStyle.kt
│ │ ├── PopupContentAnimator.kt
│ │ ├── PopupItem.kt
│ │ ├── PopupWindowImpl.kt
│ │ └── VkLibActionsListView.kt
│ └── res
│ ├── drawable-hdpi
│ └── vkim_bg_overlay.9.png
│ ├── drawable-mdpi
│ └── vkim_bg_overlay.9.png
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable-xhdpi
│ └── vkim_bg_overlay.9.png
│ ├── drawable-xxhdpi
│ └── vkim_bg_overlay.9.png
│ ├── drawable-xxxhdpi
│ └── vkim_bg_overlay.9.png
│ ├── drawable
│ ├── gradient.xml
│ ├── ic_delete_24.xml
│ ├── ic_info_24.xml
│ ├── ic_info_outline_28.xml
│ ├── ic_launcher_background.xml
│ ├── ic_more_vertical_24.xml
│ ├── ic_notifications_24.xml
│ ├── ic_replay_24.xml
│ ├── ic_report_outline_28.xml
│ ├── ic_services_outline_28.xml
│ ├── ic_settings_24.xml
│ ├── ic_settings_outline_28.xml
│ ├── ic_warning_24.xml
│ ├── remove_bg.xml
│ └── v2_dialog.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── feed_card_action.xml
│ ├── feed_card_story_large.xml
│ ├── feed_card_text.xml
│ ├── notification_generic_content.xml
│ ├── notification_simple.xml
│ ├── overlay_header.xml
│ ├── overlay_layout.xml
│ ├── plugin_manager_empty.xml
│ ├── plugin_manager_entry.xml
│ ├── plugin_manager_ui.xml
│ ├── preview.xml
│ ├── replica_popup.xml
│ └── vklib_actionslistview_entry.xml
│ ├── menu
│ └── bottom_nav_menu.xml
│ ├── mipmap-anydpi-v26
│ └── ic_launcher.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── navigation
│ └── mobile_navigation.xml
│ ├── values-night
│ ├── bools.xml
│ └── colors.xml
│ ├── values-ru
│ ├── arrays.xml
│ ├── plurals.xml
│ └── strings.xml
│ ├── values-v23
│ └── styles.xml
│ ├── values-v27
│ └── styles.xml
│ ├── values
│ ├── arrays.xml
│ ├── attrs.xml
│ ├── bools.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── plurals.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ ├── pref_about.xml
│ └── pref_general.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 | custom: ['https://qiwi.me/itaysonlab']
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Split plugins into seperate repos
2 | hf-rss-datasource
3 | hf-vkplugin
4 |
5 | # SDK as submodule
6 | hf-vkplugin
7 |
8 | # Built application files
9 | *.apk
10 | *.ap_
11 | *.aab
12 |
13 | # Files for the ART/Dalvik VM
14 | *.dex
15 |
16 | # Java class files
17 | *.class
18 |
19 | # Generated files
20 | bin/
21 | gen/
22 | out/
23 |
24 | # Gradle files
25 | .gradle/
26 | build/
27 |
28 | # Local configuration file (sdk path, etc)
29 | local.properties
30 |
31 | # Proguard folder generated by Eclipse
32 | proguard/
33 |
34 | # Log Files
35 | *.log
36 |
37 | # Android Studio Navigation editor temp files
38 | .navigation/
39 |
40 | # Android Studio captures folder
41 | captures/
42 |
43 | # IntelliJ
44 | *.iml
45 | .idea/
46 |
47 | # Keystore files
48 | # Uncomment the following lines if you do not want to check your keystore files in.
49 | #*.jks
50 | #*.keystore
51 |
52 | # External native build folder generated in Android Studio 2.2 and later
53 | .externalNativeBuild
54 |
55 | # Google Services (e.g. APIs or Firebase)
56 | google-services.json
57 |
58 | # Freeline
59 | freeline.py
60 | freeline/
61 | freeline_project_description.json
62 |
63 | # fastlane
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 | fastlane/readme.md
69 |
70 | # Obviously we don't need caches from macOS and other OS'es
71 | .DS_Store
72 | .DS_Store?
73 | ._*
74 | .Spotlight-V100
75 | .Trashes
76 | settings.gradle
77 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "homefeeder-sdk"]
2 | path = homefeeder-sdk
3 | url = https://github.com/iTaysonLab/homefeeder-sdk/
4 | [submodule "homefeeder-rss"]
5 | path = homefeeder-rss
6 | url = https://github.com/iTaysonLab/homefeeder-rss
7 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | xmlns:android
17 |
18 | ^$
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | xmlns:.*
28 |
29 | ^$
30 |
31 |
32 | BY_NAME
33 |
34 |
35 |
36 |
37 |
38 |
39 | .*:id
40 |
41 | http://schemas.android.com/apk/res/android
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | .*:name
51 |
52 | http://schemas.android.com/apk/res/android
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | name
62 |
63 | ^$
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | style
73 |
74 | ^$
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | .*
84 |
85 | ^$
86 |
87 |
88 | BY_NAME
89 |
90 |
91 |
92 |
93 |
94 |
95 | .*
96 |
97 | http://schemas.android.com/apk/res/android
98 |
99 |
100 | ANDROID_ATTRIBUTE_ORDER
101 |
102 |
103 |
104 |
105 |
106 |
107 | .*
108 |
109 | .*
110 |
111 |
112 | BY_NAME
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HomeFeeder
2 | Custom Google Now Feed replacement for launchers.
3 |
4 | ## Supported launchers
5 | - Librechair
6 | - Shade Launcher
7 | - Mostly anything with custom feed provider support
8 |
9 | ## Credits
10 | https://github.com/FabianTerhorst/DrawerOverlayService as base for overlay service
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 | apply plugin: 'kotlin-kapt'
5 | apply plugin: 'kotlin-parcelize'
6 |
7 | android {
8 | compileSdkVersion 31
9 |
10 | defaultConfig {
11 | applicationId "ua.itaysonlab.homefeeder"
12 | minSdkVersion 21
13 | targetSdkVersion 31
14 | versionCode 11
15 | versionName "alpha 1"
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled true
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 |
25 | kotlinOptions {
26 | jvmTarget = '1.8'
27 | }
28 |
29 | compileOptions {
30 | sourceCompatibility JavaVersion.VERSION_1_8
31 | targetCompatibility JavaVersion.VERSION_1_8
32 | }
33 |
34 | buildFeatures {
35 | viewBinding true
36 | }
37 | }
38 |
39 | dependencies {
40 | implementation fileTree(dir: 'libs', include: ['*.jar'])
41 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
42 | implementation 'androidx.appcompat:appcompat:1.4.1'
43 | implementation 'androidx.core:core-ktx:1.7.0'
44 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
45 | implementation 'com.google.android.material:material:1.6.0-alpha02'
46 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
47 | implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
48 | implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
49 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
50 | implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
51 | implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
52 | implementation 'androidx.preference:preference-ktx:1.2.0'
53 | implementation("io.coil-kt:coil:1.3.0")
54 |
55 | implementation project(':homefeeder-sdk')
56 | }
57 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 | #-keep class com.google.android.libraries.launcherclient.** {*;}
23 |
24 | -keep class ua.itaysonlab.hfsdk.** {
25 | *;
26 | }
27 |
28 | -repackageclasses "hfcore"
--------------------------------------------------------------------------------
/app/release/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "ua.itaysonlab.homefeeder",
8 | "variantName": "processReleaseResources",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "versionCode": 10,
14 | "versionName": "pre-alpha 10",
15 | "outputFile": "app-release.apk"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/app/release/output.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "ua.itaysonlab.homefeeder",
8 | "variantName": "release",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "properties": [],
14 | "versionCode": 8,
15 | "versionName": "8",
16 | "enabled": true,
17 | "outputFile": "app-release.apk"
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/a/LauncherOverlayBinder.java:
--------------------------------------------------------------------------------
1 | package com.google.android.a;
2 |
3 | import android.os.Binder;
4 | import android.os.IBinder;
5 | import android.os.IInterface;
6 | import android.os.Parcel;
7 | import android.os.RemoteException;
8 |
9 | public class LauncherOverlayBinder extends Binder implements IInterface {
10 | public IBinder asBinder() {
11 | return this;
12 | }
13 |
14 | protected final boolean a(int i, Parcel parcel, Parcel parcel2, int i2) throws RemoteException {//Todo: throws is new
15 | if (i > 16777215) {
16 | return super.onTransact(i, parcel, parcel2, i2);
17 | }
18 | parcel.enforceInterface(getInterfaceDescriptor());
19 | return false;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/a/a.java:
--------------------------------------------------------------------------------
1 | package com.google.android.a;
2 |
3 | import android.os.IBinder;
4 | import android.os.IInterface;
5 | import android.os.Parcel;
6 | import android.os.RemoteException;
7 |
8 | public class a implements IInterface {
9 | private final String bHh;
10 | private final IBinder binder;
11 |
12 | protected a(IBinder iBinder, String str) {
13 | this.binder = iBinder;
14 | this.bHh = str;
15 | }
16 |
17 | public IBinder asBinder() {
18 | return this.binder;
19 | }
20 |
21 | protected final Parcel pg() {
22 | Parcel obtain = Parcel.obtain();
23 | obtain.writeInterfaceToken(this.bHh);
24 | return obtain;
25 | }
26 |
27 | //Todo: different from source
28 | public final Parcel a(int i, Parcel parcel) {
29 | IBinder iBinder;
30 | Parcel obtain = Parcel.obtain();
31 | try {
32 | iBinder = this.binder;
33 | iBinder.transact(i, parcel, obtain, 0);
34 | obtain.readException();
35 | } catch (RuntimeException | RemoteException e) {
36 | parcel = null;
37 | //throw e;
38 | } finally {
39 | obtain.recycle();
40 | }
41 | return parcel;
42 | }
43 |
44 | //Todo: different from source
45 | protected final void c(int i, Parcel parcel) {
46 | try {
47 | this.binder.transact(i, parcel, null, 1);
48 | } catch (RemoteException e) {
49 | e.printStackTrace();
50 | } finally {
51 | parcel.recycle();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/a/c.java:
--------------------------------------------------------------------------------
1 | package com.google.android.a;
2 |
3 | import android.os.IInterface;
4 | import android.os.Parcel;
5 | import android.os.Parcelable;
6 | import android.os.Parcelable.Creator;
7 | import java.util.HashMap;
8 |
9 | public class c {
10 | private c() {
11 | }
12 |
13 | public static boolean a(Parcel parcel) {
14 | return parcel.readInt() == 1;
15 | }
16 |
17 | public static void a(Parcel parcel, boolean z) {
18 | parcel.writeInt(z ? 1 : 0);
19 | }
20 |
21 | public static Parcelable a(Parcel parcel, Creator creator) {
22 | if (parcel.readInt() == 0) {
23 | return null;
24 | }
25 | return (Parcelable) creator.createFromParcel(parcel);
26 | }
27 |
28 | public static void a(Parcel parcel, Parcelable parcelable) {
29 | if (parcelable == null) {
30 | parcel.writeInt(0);
31 | return;
32 | }
33 | parcel.writeInt(1);
34 | parcelable.writeToParcel(parcel, 0);
35 | }
36 |
37 | public static void a(Parcel parcel, IInterface iInterface) {
38 | if (iInterface == null) {
39 | parcel.writeStrongBinder(null);
40 | } else {
41 | parcel.writeStrongBinder(iInterface.asBinder());
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/apps/gsa/nowoverlayservice/ConfigurationOverlayController.kt:
--------------------------------------------------------------------------------
1 | package com.google.android.apps.gsa.nowoverlayservice
2 |
3 | import android.app.Service
4 | import android.content.Context
5 | import android.content.res.Configuration
6 |
7 | import com.google.android.libraries.gsa.d.a.OverlayController
8 | import com.google.android.libraries.gsa.d.a.OverlaysController
9 | import com.google.android.libraries.gsa.d.a.v
10 |
11 | import ua.itaysonlab.homefeeder.overlay.OverlayKt
12 |
13 | class ConfigurationOverlayController(private val service: Service) : OverlaysController(service) {
14 | override fun Hx() = 24
15 |
16 | override fun createController(
17 | configuration: Configuration?,
18 | i: Int,
19 | i2: Int
20 | ): OverlayController = OverlayKt(if (configuration != null) service.createConfigurationContext(configuration) else service)
21 |
22 | override fun HA() = v()
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/BaseCallback.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.os.Handler.Callback;
4 | import android.os.Message;
5 | import java.io.PrintWriter;
6 |
7 | class BaseCallback implements Callback {
8 |
9 | BaseCallback() {
10 | }
11 |
12 | public boolean handleMessage(Message message) {
13 | return true;
14 | }
15 |
16 | public void dump(PrintWriter printWriter, String str) {
17 | printWriter.println(String.valueOf(str).concat("BaseCallback: nothing to dump"));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/ByteBundleHolder.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.os.Bundle;
4 |
5 | final class ByteBundleHolder {
6 |
7 | private final Bundle extras;
8 | private final byte[] bytes;
9 |
10 | public ByteBundleHolder(byte[] bArr, Bundle bundle) {
11 | this.bytes = bArr;
12 | this.extras = bundle;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/DialogListeners.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.content.DialogInterface.OnDismissListener;
4 | import android.content.DialogInterface.OnShowListener;
5 |
6 | interface DialogListeners extends OnDismissListener, OnShowListener {
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/DialogOverlayController.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.os.Build.VERSION;
8 | import android.os.Bundle;
9 | import android.view.ActionMode;
10 | import android.view.ContextThemeWrapper;
11 | import android.view.KeyEvent;
12 | import android.view.Menu;
13 | import android.view.MenuItem;
14 | import android.view.MotionEvent;
15 | import android.view.SearchEvent;
16 | import android.view.View;
17 | import android.view.Window;
18 | import android.view.Window.Callback;
19 | import android.view.WindowManager;
20 | import android.view.WindowManager.LayoutParams;
21 | import android.view.accessibility.AccessibilityEvent;
22 |
23 | import java.util.HashSet;
24 |
25 | class DialogOverlayController extends ContextThemeWrapper implements Callback, DialogListeners {
26 |
27 | public WindowManager windowManager;
28 | public final Window window;
29 | private final HashSet dialogs = new HashSet<>();
30 | public View windowView;
31 |
32 | DialogOverlayController(Context context, int theme, int dialogTheme) {
33 | super(context, theme);
34 | Dialog dialog = new Dialog(context, dialogTheme);
35 | this.window = dialog.getWindow();
36 | this.window.setCallback(this);
37 | Window window = this.window;
38 | if (VERSION.SDK_INT >= 21) {
39 | //window.setStatusBarColor(0);
40 | //window.setNavigationBarColor(0);
41 | window.addFlags(Integer.MIN_VALUE);
42 | } else if (VERSION.SDK_INT >= 19) {
43 | window.addFlags(201326592);
44 | }
45 | }
46 |
47 | void onBackPressed() {
48 | }
49 |
50 | public boolean dispatchKeyEvent(KeyEvent keyEvent) {
51 | if (keyEvent.getKeyCode() != 4 || keyEvent.getAction() != 1 || keyEvent.isCanceled()) {
52 | return this.window.superDispatchKeyEvent(keyEvent);
53 | }
54 | onBackPressed();
55 | return true;
56 | }
57 |
58 | public boolean dispatchKeyShortcutEvent(KeyEvent keyEvent) {
59 | return this.window.superDispatchKeyShortcutEvent(keyEvent);
60 | }
61 |
62 | public boolean dispatchTouchEvent(MotionEvent motionEvent) {
63 | return this.window.superDispatchTouchEvent(motionEvent);
64 | }
65 |
66 | public boolean dispatchTrackballEvent(MotionEvent motionEvent) {
67 | return this.window.superDispatchTrackballEvent(motionEvent);
68 | }
69 |
70 | public boolean dispatchGenericMotionEvent(MotionEvent motionEvent) {
71 | return this.window.superDispatchGenericMotionEvent(motionEvent);
72 | }
73 |
74 | public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
75 | return false;
76 | }
77 |
78 | public View onCreatePanelView(int i) {
79 | return null;
80 | }
81 |
82 | public boolean onCreatePanelMenu(int i, Menu menu) {
83 | return false;
84 | }
85 |
86 | public boolean onPreparePanel(int i, View view, Menu menu) {
87 | return true;
88 | }
89 |
90 | public boolean onMenuOpened(int i, Menu menu) {
91 | return true;
92 | }
93 |
94 | public boolean onMenuItemSelected(int i, MenuItem menuItem) {
95 | return false;
96 | }
97 |
98 | public void onWindowAttributesChanged(LayoutParams layoutParams) {
99 | if (this.windowView != null) {
100 | this.windowManager.updateViewLayout(this.windowView, layoutParams);
101 | }
102 | }
103 |
104 | public void onContentChanged() {
105 | }
106 |
107 | public void onWindowFocusChanged(boolean z) {
108 | }
109 |
110 | public void onAttachedToWindow() {
111 | }
112 |
113 | public void onDetachedFromWindow() {
114 | }
115 |
116 | public void onPanelClosed(int i, Menu menu) {
117 | }
118 |
119 | public boolean onSearchRequested() {
120 | return false;
121 | }
122 |
123 | public boolean onSearchRequested(SearchEvent searchEvent) {
124 | return false;
125 | }
126 |
127 | public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
128 | return null;
129 | }
130 |
131 | public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int i) {
132 | return null;
133 | }
134 |
135 | public void onActionModeStarted(ActionMode actionMode) {
136 | }
137 |
138 | public void onActionModeFinished(ActionMode actionMode) {
139 | }
140 |
141 | public void startActivity(Intent intent) {
142 | super.startActivity(intent.addFlags(268435456));
143 | }
144 |
145 | public void startActivity(Intent intent, Bundle bundle) {
146 | super.startActivity(intent.addFlags(268435456), bundle);
147 | }
148 |
149 | public void onShow(DialogInterface dialogInterface) {
150 | this.dialogs.add(dialogInterface);
151 | }
152 |
153 | public void onDismiss(DialogInterface dialogInterface) {
154 | this.dialogs.remove(dialogInterface);
155 | }
156 |
157 | final void cnB() {
158 | if (!this.dialogs.isEmpty()) {
159 | Dialog[] dialogArr = this.dialogs.toArray(new Dialog[this.dialogs.size()]);
160 | this.dialogs.clear();
161 | for (Dialog dismiss : dialogArr) {
162 | dismiss.dismiss();
163 | }
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/MinusOneOverlayCallback.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.content.res.Configuration;
4 | import android.os.Message;
5 |
6 | import java.io.PrintWriter;
7 |
8 | public final class MinusOneOverlayCallback extends OverlayControllerCallback {
9 |
10 | private final OverlaysController overlaysController;
11 |
12 | public MinusOneOverlayCallback(OverlaysController overlaysControllerVar, OverlayControllerBinder overlayControllerBinderVar) {
13 | super(overlayControllerBinderVar, 3);
14 | this.overlaysController = overlaysControllerVar;
15 | }
16 |
17 | final OverlayController createController(Configuration configuration) {
18 | return this.overlaysController.createController(configuration, this.overlayControllerBinder.mServerVersion, this.overlayControllerBinder.mClientVersion);
19 | }
20 |
21 | public final void dump(PrintWriter printWriter, String str) {
22 | printWriter.println(String.valueOf(str).concat("MinusOneOverlayCallback"));
23 | super.dump(printWriter, str);
24 | }
25 |
26 | public final boolean handleMessage(Message message) {
27 | if (super.handleMessage(message)) {
28 | return true;
29 | }
30 | OverlayController overlayControllerVar;
31 | long when;
32 | switch (message.what) {
33 | case 3:
34 | if (this.overlayController != null) {
35 | overlayControllerVar = this.overlayController;
36 | when = message.getWhen();
37 | if (!overlayControllerVar.cnD()) {
38 | SlidingPanelLayout slidingPanelLayoutVar = overlayControllerVar.slidingPanelLayout;
39 | if (slidingPanelLayoutVar.uoC < slidingPanelLayoutVar.mTouchSlop) {
40 | overlayControllerVar.slidingPanelLayout.BM(0);
41 | overlayControllerVar.mAcceptExternalMove = true;
42 | overlayControllerVar.unX = 0;
43 | overlayControllerVar.slidingPanelLayout.mForceDrag = true;
44 | overlayControllerVar.obZ = when - 30;
45 | overlayControllerVar.b(0, overlayControllerVar.unX, overlayControllerVar.obZ);
46 | overlayControllerVar.b(2, overlayControllerVar.unX, when);
47 | }
48 | }
49 | }
50 | return true;
51 | case 4:
52 | if (this.overlayController != null) {
53 | overlayControllerVar = this.overlayController;
54 | float floatValue = (float) message.obj;
55 | when = message.getWhen();
56 | if (overlayControllerVar.mAcceptExternalMove) {
57 | overlayControllerVar.unX = (int) (floatValue * ((float) overlayControllerVar.slidingPanelLayout.getMeasuredWidth()));
58 | overlayControllerVar.b(2, overlayControllerVar.unX, when);
59 | }
60 | }
61 | return true;
62 | case 5:
63 | if (this.overlayController != null) {
64 | overlayControllerVar = this.overlayController;
65 | when = message.getWhen();
66 | if (overlayControllerVar.mAcceptExternalMove) {
67 | overlayControllerVar.b(1, overlayControllerVar.unX, when);
68 | }
69 | overlayControllerVar.mAcceptExternalMove = false;
70 | }
71 | return true;
72 | default:
73 | return false;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/OverlayControllerLayoutChangeListener.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.os.Build;
4 | import android.view.View;
5 | import android.view.View.OnLayoutChangeListener;
6 | import android.view.WindowManager.LayoutParams;
7 |
8 | final class OverlayControllerLayoutChangeListener implements OnLayoutChangeListener {
9 |
10 | private final OverlayController overlayController;
11 |
12 | OverlayControllerLayoutChangeListener(OverlayController overlayControllerVar) {
13 | this.overlayController = overlayControllerVar;
14 | }
15 |
16 | public final void onLayoutChange(View view, int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8) {
17 | this.overlayController.window.getDecorView().removeOnLayoutChangeListener(this);
18 | if (this.overlayController.panelState == PanelState.CLOSED) {//Todo: PanelState.uoe was default
19 | OverlayController overlayControllerVar = this.overlayController;
20 | LayoutParams attributes = overlayControllerVar.window.getAttributes();
21 | if (Build.VERSION.SDK_INT >= 26) {
22 | float f = attributes.alpha;
23 | attributes.alpha = 0.0f;
24 | if (f != attributes.alpha) {
25 | overlayControllerVar.window.setAttributes(attributes);
26 | return;
27 | }
28 | return;
29 | }
30 | attributes.x = overlayControllerVar.mWindowShift;
31 | attributes.flags |= 512;
32 | overlayControllerVar.unZ = false;
33 | overlayControllerVar.window.setAttributes(attributes);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/OverlayControllerSlidingPanelLayout.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.graphics.Rect;
4 | import android.view.MotionEvent;
5 |
6 | public final class OverlayControllerSlidingPanelLayout extends SlidingPanelLayout {
7 |
8 | private final OverlayController overlayController;
9 |
10 | public OverlayControllerSlidingPanelLayout(OverlayController overlayControllerVar) {
11 | super(overlayControllerVar);
12 | this.overlayController = overlayControllerVar;
13 | }
14 |
15 | protected final void determineScrollingStart(MotionEvent motionEvent, float f) {
16 | Object obj = 1;
17 | if (motionEvent.findPointerIndex(this.mActivePointerId) != -1) {
18 | float x = motionEvent.getX() - this.mDownX;
19 | float abs = Math.abs(x);
20 | float abs2 = Math.abs(motionEvent.getY() - this.mDownY);
21 | if (Float.compare(abs, 0.0f) != 0) {
22 | abs = (float) Math.atan((double) (abs2 / abs));
23 | Object obj2;
24 | if (this.mIsRtl) {
25 | obj2 = x < 0.0f ? 1 : null;
26 | } else if (x > 0.0f) {
27 | obj2 = 1;//TODO: different from source
28 | } else {
29 | obj2 = null;
30 | }
31 | if (!this.mIsPanelOpen || this.mIsPageMoving) {
32 | obj = null;
33 | }
34 | if (obj != null && obj2 != null) {//TODO: different from source
35 | return;
36 | }
37 | if ((obj != null && this.uoH.cnI()) || abs > 1.0471976f) {
38 | return;
39 | }
40 | if (abs > 0.5235988f) {
41 | super.determineScrollingStart(motionEvent, (((float) Math.sqrt((double) ((abs - 0.5235988f) / 0.5235988f))) * 4.0f) + 1.0f);
42 | } else {
43 | super.determineScrollingStart(motionEvent, f);
44 | }
45 | }
46 | }
47 | }
48 |
49 | protected final boolean fitSystemWindows(Rect rect) {
50 | return !this.overlayController.unZ || super.fitSystemWindows(rect);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/OverlayControllerStateChanger.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.os.Build;
4 | import android.view.WindowManager.LayoutParams;
5 |
6 | final class OverlayControllerStateChanger implements t {
7 |
8 | private final OverlayController overlayController;
9 |
10 | OverlayControllerStateChanger(OverlayController overlayControllerVar) {
11 | this.overlayController = overlayControllerVar;
12 | }
13 |
14 | public final void drag() {
15 | OverlayController overlayControllerVar = this.overlayController;
16 | PanelState panelStateVar = PanelState.DRAGGING;//Todo: PanelState.uof was default
17 | if (overlayControllerVar.panelState != panelStateVar) {
18 | overlayControllerVar.panelState = panelStateVar;
19 | overlayControllerVar.setState(overlayControllerVar.panelState);
20 | }
21 | overlayControllerVar = this.overlayController;
22 | LayoutParams attributes = overlayControllerVar.window.getAttributes();
23 | if (Build.VERSION.SDK_INT >= 26) {
24 | float f = attributes.alpha;
25 | attributes.alpha = 1.0f;
26 | if (f != attributes.alpha) {
27 | overlayControllerVar.window.setAttributes(attributes);
28 | return;
29 | }
30 | return;
31 | }
32 | attributes.x = 0;
33 | attributes.flags &= -513;
34 | overlayControllerVar.unZ = true;
35 | overlayControllerVar.window.setAttributes(attributes);
36 | }
37 |
38 | public final void cnF() {
39 | OverlayController overlayControllerVar = this.overlayController;
40 | PanelState panelStateVar = PanelState.DRAGGING;//Todo: PanelState.uof was default
41 | if (overlayControllerVar.panelState != panelStateVar) {
42 | overlayControllerVar.panelState = panelStateVar;
43 | overlayControllerVar.setState(overlayControllerVar.panelState);
44 | }
45 | this.overlayController.setVisible(true);
46 | overlayControllerVar = this.overlayController;
47 | LayoutParams attributes = overlayControllerVar.window.getAttributes();
48 | if (Build.VERSION.SDK_INT >= 26) {
49 | float f = attributes.alpha;
50 | attributes.alpha = 1.0f;
51 | if (f != attributes.alpha) {
52 | overlayControllerVar.window.setAttributes(attributes);
53 | return;
54 | }
55 | return;
56 | }
57 | attributes.x = 0;
58 | attributes.flags &= -513;
59 | overlayControllerVar.unZ = true;
60 | overlayControllerVar.window.setAttributes(attributes);
61 | }
62 |
63 | public final void oc(boolean z) {
64 | if (z) {
65 | this.overlayController.Hn();
66 | }
67 | OverlayController overlayControllerVar = this.overlayController;
68 | PanelState panelStateVar = PanelState.DRAGGING;//Todo: PanelState.uof was default
69 | if (overlayControllerVar.panelState != panelStateVar) {
70 | overlayControllerVar.panelState = panelStateVar;
71 | overlayControllerVar.setState(overlayControllerVar.panelState);
72 | }
73 | this.overlayController.setVisible(false);
74 | }
75 |
76 | public final void open() {
77 | OverlayController overlayControllerVar = this.overlayController;
78 | PanelState panelStateVar = PanelState.OPEN_AS_DRAWER;//Todo: PanelState.uog was default
79 | if (overlayControllerVar.panelState != panelStateVar) {
80 | overlayControllerVar.panelState = panelStateVar;
81 | overlayControllerVar.setState(overlayControllerVar.panelState);
82 | }
83 | }
84 |
85 | public final void D(float f) {
86 | if (this.overlayController.uoa != null && !Float.isNaN(f)) {
87 | try {
88 | this.overlayController.uoa.aK(f);
89 | this.overlayController.onScroll(f);
90 | } catch (Throwable ignored) {
91 |
92 | }
93 | }
94 | }
95 |
96 | public final void close() {
97 | OverlayController overlayControllerVar = this.overlayController;
98 | LayoutParams attributes = overlayControllerVar.window.getAttributes();
99 | if (Build.VERSION.SDK_INT >= 26) {
100 | float f = attributes.alpha;
101 | attributes.alpha = 0.0f;
102 | if (f != attributes.alpha) {
103 | overlayControllerVar.window.setAttributes(attributes);
104 | }
105 | } else {
106 | attributes.x = overlayControllerVar.mWindowShift;
107 | attributes.flags |= 512;
108 | overlayControllerVar.unZ = false;
109 | overlayControllerVar.window.setAttributes(attributes);
110 | }
111 | overlayControllerVar = this.overlayController;
112 | PanelState panelStateVar = PanelState.CLOSED;//Todo: PanelState.uoe was default
113 | if (overlayControllerVar.panelState != panelStateVar) {
114 | overlayControllerVar.panelState = panelStateVar;
115 | overlayControllerVar.setState(overlayControllerVar.panelState);
116 | }
117 | }
118 |
119 | public final boolean cnI() {
120 | return this.overlayController.Ho();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/PanelState.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | public enum PanelState {
4 | CLOSED,//Todo: PanelState.uoe was default
5 | DRAGGING,//Todo: PanelState.uof was default
6 | OPEN_AS_DRAWER,//Todo: PanelState.uog was default
7 | OPEN_AS_LAYER//Todo: PanelState.uoh was default
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/SlidingPanelLayoutInterpolator.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.animation.ObjectAnimator;
6 | import android.view.animation.Interpolator;
7 |
8 | final class SlidingPanelLayoutInterpolator extends AnimatorListenerAdapter implements Interpolator {
9 |
10 | private ObjectAnimator mAnimator;
11 | int mFinalX;
12 | private final SlidingPanelLayout slidingPanelLayout;
13 |
14 | public SlidingPanelLayoutInterpolator(SlidingPanelLayout slidingPanelLayoutVar) {
15 | this.slidingPanelLayout = slidingPanelLayoutVar;
16 | }
17 |
18 | public final void cnP() {
19 | if (this.mAnimator != null) {
20 | this.mAnimator.removeAllListeners();
21 | this.mAnimator.cancel();
22 | }
23 | }
24 |
25 | public final void dt(int i, int i2) {
26 | cnP();
27 | this.mFinalX = i;
28 | if (i2 > 0) {
29 | this.mAnimator = ObjectAnimator.ofInt(this.slidingPanelLayout, SlidingPanelLayout.PANEL_X, i).setDuration((long) i2);
30 | this.mAnimator.setInterpolator(this);
31 | this.mAnimator.addListener(this);
32 | this.mAnimator.start();
33 | return;
34 | }
35 | onAnimationEnd(null);
36 | }
37 |
38 | public final boolean isFinished() {
39 | return this.mAnimator == null;
40 | }
41 |
42 | public final void onAnimationEnd(Animator animator) {
43 | this.mAnimator = null;
44 | this.slidingPanelLayout.BM(this.mFinalX);
45 | SlidingPanelLayout slidingPanelLayoutVar = this.slidingPanelLayout;
46 | if (slidingPanelLayoutVar.mSettling) {
47 | slidingPanelLayoutVar.mSettling = false;
48 | if (slidingPanelLayoutVar.uoC == 0) {
49 | slidingPanelLayoutVar.cnO();
50 | slidingPanelLayoutVar.mIsPanelOpen = false;
51 | slidingPanelLayoutVar.mIsPageMoving = false;
52 | if (slidingPanelLayoutVar.uoH != null) {
53 | slidingPanelLayoutVar.uoH.close();
54 | }
55 | } else if (slidingPanelLayoutVar.uoC == slidingPanelLayoutVar.getMeasuredWidth()) {
56 | slidingPanelLayoutVar.cnG();
57 | }
58 | }
59 | }
60 |
61 | public final float getInterpolation(float f) {
62 | float f2 = f - 1.0f;
63 | return (f2 * (((f2 * f2) * f2) * f2)) + 1.0f;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/SlidingPanelLayoutProperty.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.util.Property;
4 |
5 | final class SlidingPanelLayoutProperty extends Property {
6 |
7 | SlidingPanelLayoutProperty(Class cls, String str) {
8 | super(cls, str);
9 | }
10 |
11 | public final /* synthetic */ Object get(Object obj) {
12 | return ((SlidingPanelLayout) obj).uoC;
13 | }
14 |
15 | public final /* synthetic */ void set(Object obj, Object obj2) {
16 | ((SlidingPanelLayout) obj).BM((Integer) obj2);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/TransparentOverlayController.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | import android.os.Build;
4 | import android.view.WindowManager.LayoutParams;
5 |
6 | final class TransparentOverlayController implements t {
7 |
8 | private final OverlayController overlayController;
9 |
10 | TransparentOverlayController(OverlayController overlayControllerVar) {
11 | this.overlayController = overlayControllerVar;
12 | }
13 |
14 | public final void drag() {
15 |
16 | }
17 |
18 | public final void cnF() {
19 | }
20 |
21 | public final void oc(boolean z) {
22 | }
23 |
24 | public final void open() {
25 | this.overlayController.setVisible(true);
26 | OverlayController overlayControllerVar = this.overlayController;
27 | LayoutParams attributes = overlayControllerVar.window.getAttributes();
28 | if (Build.VERSION.SDK_INT >= 26) {
29 | float f = attributes.alpha;
30 | attributes.alpha = 1.0f;
31 | if (f != attributes.alpha) {
32 | overlayControllerVar.window.setAttributes(attributes);
33 | }
34 | } else {
35 | attributes.x = 0;
36 | attributes.flags &= -513;
37 | overlayControllerVar.unZ = true;
38 | overlayControllerVar.window.setAttributes(attributes);
39 | }
40 | overlayControllerVar = this.overlayController;
41 | PanelState panelStateVar = PanelState.OPEN_AS_LAYER;//Todo: PanelState.uoh was default
42 | if (overlayControllerVar.panelState != panelStateVar) {
43 | overlayControllerVar.panelState = panelStateVar;
44 | overlayControllerVar.setState(overlayControllerVar.panelState);
45 | }
46 | }
47 |
48 | public final void close() {
49 | OverlayController overlayControllerVar = this.overlayController;
50 | LayoutParams attributes = overlayControllerVar.window.getAttributes();
51 | if (Build.VERSION.SDK_INT >= 26) {
52 | float f = attributes.alpha;
53 | attributes.alpha = 0.0f;
54 | if (f != attributes.alpha) {
55 | overlayControllerVar.window.setAttributes(attributes);
56 | }
57 | } else {
58 | attributes.x = overlayControllerVar.mWindowShift;
59 | attributes.flags |= 512;
60 | overlayControllerVar.unZ = false;
61 | overlayControllerVar.window.setAttributes(attributes);
62 | }
63 | this.overlayController.setVisible(false);
64 | overlayControllerVar = this.overlayController;
65 | PanelState panelStateVar = PanelState.CLOSED;//Todo: PanelState.uoe was default
66 | if (overlayControllerVar.panelState != panelStateVar) {
67 | overlayControllerVar.panelState = panelStateVar;
68 | overlayControllerVar.setState(overlayControllerVar.panelState);
69 | }
70 | this.overlayController.slidingPanelLayout.uoH = this.overlayController.overlayControllerStateChanger;
71 | }
72 |
73 | public final void D(float f) {
74 | }
75 |
76 | public final boolean cnI() {
77 | return true;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/t.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | interface t {
4 | void D(float f);
5 |
6 | void drag();
7 |
8 | void cnF();
9 |
10 | void open();
11 |
12 | void close();
13 |
14 | boolean cnI();
15 |
16 | void oc(boolean z);
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/gsa/d/a/v.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.gsa.d.a;
2 |
3 | public class v {
4 | public String HB() {
5 | return null;
6 | }
7 |
8 | public boolean HC() {
9 | return false;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/i/LauncherOverlayInterfaceBinder.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.i;
2 |
3 | import android.os.Bundle;
4 | import android.os.IBinder;
5 | import android.os.IInterface;
6 | import android.os.Parcel;
7 | import android.os.RemoteException;
8 | import android.view.WindowManager.LayoutParams;
9 |
10 | import com.google.android.a.LauncherOverlayBinder;
11 | import com.google.android.a.c;
12 | //import com.google.android.gms.dynamite.descriptors.com.google.android.gms.ads.dynamite.ModuleDescriptor;
13 |
14 |
15 | public abstract class LauncherOverlayInterfaceBinder extends LauncherOverlayBinder implements a {
16 |
17 | protected LauncherOverlayInterfaceBinder() {
18 | attachInterface(this, "com.google.android.libraries.launcherclient.ILauncherOverlay");
19 | }
20 |
21 | public boolean onTransact(int i, Parcel parcel, Parcel parcel2, int i2) throws RemoteException {//Todo: throws is new
22 | d dVar = null;
23 | if (a(i, parcel, parcel2, i2)) {
24 | return true;
25 | }
26 | IBinder readStrongBinder;
27 | IInterface queryLocalInterface;
28 | boolean HC;
29 | switch (i) {
30 | case 1:
31 | cnK();
32 | break;
33 | case 2:
34 | aL(parcel.readFloat());
35 | break;
36 | case 3:
37 | cnL();
38 | break;
39 | case 4:
40 | LayoutParams layoutParams = (LayoutParams) c.a(parcel, LayoutParams.CREATOR);
41 | readStrongBinder = parcel.readStrongBinder();
42 | if (readStrongBinder != null) {
43 | queryLocalInterface = readStrongBinder.queryLocalInterface("com.google.android.libraries.launcherclient.ILauncherOverlayCallback");
44 | if (queryLocalInterface instanceof d) {
45 | dVar = (d) queryLocalInterface;
46 | } else {
47 | dVar = new f(readStrongBinder);
48 | }
49 | }
50 | a(layoutParams, dVar, parcel.readInt());
51 | break;
52 | case 5:
53 | od(c.a(parcel));
54 | break;
55 | case 6:
56 | fI(parcel.readInt());
57 | break;
58 | case 7:
59 | onPause();
60 | break;
61 | case 8:
62 | onResume();
63 | break;
64 | case 9:
65 | BK(parcel.readInt());
66 | break;
67 | case 10:
68 | oe(c.a(parcel));
69 | break;
70 | case 11:
71 | String HB = HB();
72 | parcel2.writeNoException();
73 | parcel2.writeString(HB);
74 | break;
75 | case /*ModuleDescriptor.MODULE_VERSION*/12 /*12*/://Todo: modified, 12 was always there but the constant was there before
76 | HC = HC();
77 | parcel2.writeNoException();
78 | c.a(parcel2, HC);
79 | break;
80 | case 13:
81 | parcel2.writeNoException();
82 | c.a(parcel2, true);
83 | break;
84 | case 14:
85 | Bundle bundle = (Bundle) c.a(parcel, Bundle.CREATOR);
86 | readStrongBinder = parcel.readStrongBinder();
87 | if (readStrongBinder != null) {
88 | queryLocalInterface = readStrongBinder.queryLocalInterface("com.google.android.libraries.launcherclient.ILauncherOverlayCallback");
89 | if (queryLocalInterface instanceof d) {
90 | dVar = (d) queryLocalInterface;
91 | } else {
92 | dVar = new f(readStrongBinder);
93 | }
94 | }
95 | a(bundle, dVar);
96 | break;
97 | case 16:
98 | BJ(parcel.readInt());
99 | break;
100 | case 17:
101 | HC = a(parcel.createByteArray(), (Bundle) c.a(parcel, Bundle.CREATOR));
102 | parcel2.writeNoException();
103 | c.a(parcel2, HC);
104 | break;
105 | default:
106 | return false;
107 | }
108 | return true;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/i/a.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.i;
2 |
3 | import android.os.Bundle;
4 | import android.os.IInterface;
5 | import android.view.WindowManager.LayoutParams;
6 |
7 | public interface a extends IInterface {
8 | void BJ(int i);
9 |
10 | void BK(int i);
11 |
12 | String HB();
13 |
14 | boolean HC();
15 |
16 | void a(Bundle bundle, d dVar);
17 |
18 | void a(LayoutParams layoutParams, d dVar, int i);
19 |
20 | boolean a(byte[] bArr, Bundle bundle);
21 |
22 | void aL(float f);
23 |
24 | void cnK();
25 |
26 | void cnL();
27 |
28 | void fI(int i);
29 |
30 | void od(boolean z);
31 |
32 | void oe(boolean z);
33 |
34 | void onPause();
35 |
36 | void onResume();
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/i/d.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.i;
2 |
3 | import android.os.IInterface;
4 |
5 | public interface d extends IInterface {
6 | void BI(int i);
7 |
8 | void aK(float f);
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/android/libraries/i/f.java:
--------------------------------------------------------------------------------
1 | package com.google.android.libraries.i;
2 |
3 | import android.os.IBinder;
4 | import android.os.Parcel;
5 | import com.google.android.a.a;
6 |
7 | public final class f extends a implements d {
8 |
9 | f(IBinder iBinder) {
10 | super(iBinder, "com.google.android.libraries.launcherclient.ILauncherOverlayCallback");
11 | }
12 |
13 | public final void aK(float f) {
14 | Parcel pg = pg();
15 | pg.writeFloat(f);
16 | c(1, pg);
17 | }
18 |
19 | public final void BI(int i) {
20 | Parcel pg = pg();
21 | pg.writeInt(i);
22 | c(2, pg);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/HFApplication.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder
2 |
3 | import android.app.Application
4 | import android.app.Notification
5 | import ua.itaysonlab.homefeeder.utils.Logger
6 | import android.content.pm.PackageManager
7 | import android.graphics.drawable.BitmapDrawable
8 | import android.graphics.drawable.Drawable
9 | import android.os.Build
10 | import androidx.core.graphics.drawable.toDrawable
11 | import ua.itaysonlab.homefeeder.pluginsystem.PluginFetcher
12 | import ua.itaysonlab.homefeeder.utils.OverlayBridge
13 |
14 | class HFApplication: Application() {
15 | companion object {
16 | const val ACTION_MANAGE_LISTENERS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"
17 |
18 | lateinit var instance: HFApplication
19 | val bridge = OverlayBridge()
20 |
21 | fun getAppNameByPkg(pkg: String): CharSequence {
22 | val ai = try {
23 | instance.packageManager.getApplicationInfo(pkg, 0)
24 | } catch (e: PackageManager.NameNotFoundException) {
25 | null
26 | }
27 | return if (ai != null) instance.packageManager.getApplicationLabel(ai) else "Unknown"
28 | }
29 |
30 | fun getSmallIcon(notification: Notification, pkg: String): Drawable {
31 | return try {
32 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
33 | notification.smallIcon.loadDrawable(instance)
34 | } else {
35 | instance.packageManager.getResourcesForApplication(pkg).getDrawable(notification.icon, null)
36 | }
37 | } catch (e: Exception) {
38 | instance.packageManager.getApplicationIcon(pkg)
39 | }
40 | }
41 |
42 | fun getSmallIcon(pkg: String): Drawable {
43 | return instance.packageManager.getApplicationIcon(pkg)
44 | }
45 |
46 | fun getLargeIcon(notification: Notification): BitmapDrawable? {
47 | return try {
48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
49 | notification.getLargeIcon().loadDrawable(instance) as? BitmapDrawable
50 | } else {
51 | notification.largeIcon.toDrawable(instance.resources)
52 | }
53 | } catch (e: Exception) {
54 | null
55 | }
56 | }
57 | }
58 |
59 | override fun onCreate() {
60 | super.onCreate()
61 | Logger.log("Application", "Starting HomeFeeder ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})...")
62 | instance = this
63 | PluginFetcher.init(instance)
64 | }
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/activites/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.activites
2 |
3 | import android.Manifest
4 | import android.content.pm.PackageManager
5 | import android.os.Bundle
6 | import androidx.appcompat.app.AppCompatActivity
7 | import androidx.core.app.ActivityCompat
8 | import androidx.core.content.ContextCompat
9 | import androidx.navigation.findNavController
10 | import androidx.navigation.ui.AppBarConfiguration
11 | import androidx.navigation.ui.setupActionBarWithNavController
12 | import androidx.navigation.ui.setupWithNavController
13 | import com.google.android.material.bottomnavigation.BottomNavigationView
14 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
15 | import ua.itaysonlab.homefeeder.R
16 |
17 | class MainActivity : AppCompatActivity() {
18 | override fun onCreate(savedInstanceState: Bundle?) {
19 | super.onCreate(savedInstanceState)
20 | setContentView(R.layout.activity_main)
21 | setSupportActionBar(findViewById(R.id.toolbar))
22 | val navView: BottomNavigationView = findViewById(R.id.nav_view)
23 |
24 | val navController = findNavController(R.id.nav_host_fragment)
25 | val appBarConfiguration = AppBarConfiguration(
26 | setOf(
27 | R.id.navigation_plugins, R.id.navigation_settings, R.id.navigation_about
28 | )
29 | )
30 |
31 | setupActionBarWithNavController(navController, appBarConfiguration)
32 | navView.setupWithNavController(navController)
33 |
34 | checkStoragePermission()
35 | }
36 |
37 | private fun checkStoragePermission() {
38 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
39 | showStorageAlert()
40 | }
41 | }
42 |
43 | override fun onRequestPermissionsResult(
44 | requestCode: Int,
45 | permissions: Array,
46 | grantResults: IntArray
47 | ) {
48 | super.onRequestPermissionsResult(requestCode, permissions, grantResults)
49 | if (requestCode == 1) {
50 | if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
51 | findNavController(R.id.nav_host_fragment).navigate(R.id.navigation_settings)
52 | } else {
53 | showStorageAlert()
54 | }
55 | }
56 | }
57 |
58 | private fun showStorageAlert() {
59 | MaterialAlertDialogBuilder(this).apply {
60 | setTitle(R.string.storage_alert)
61 | setMessage(R.string.storage_desc)
62 | setPositiveButton(R.string.storage_action) { _, _ ->
63 | ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
64 | }
65 | setNeutralButton(R.string.cancel, null)
66 | }.show()
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/fragments/AboutFragment.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.fragments
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import androidx.preference.Preference
8 | import ua.itaysonlab.homefeeder.BuildConfig
9 | import ua.itaysonlab.homefeeder.R
10 | import ua.itaysonlab.homefeeder.fragments.base.FixedPreferencesFragment
11 |
12 | class AboutFragment : FixedPreferencesFragment() {
13 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
14 | setPreferencesFromResource(R.xml.pref_about, rootKey)
15 |
16 | findPreference("about_app")!!.summary = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
17 |
18 | val tg = findPreference("about_tg")!!
19 | val tgdev = findPreference("about_tg_dev")!!
20 | val git = findPreference("about_source")!!
21 |
22 | tg.summary = "@homefeeder"
23 | tg.setOnPreferenceClickListener {
24 | openLink(requireActivity(), "https://t.me/homefeeder")
25 | true
26 | }
27 | tgdev.summary = "@itaysonlab"
28 | tgdev.setOnPreferenceClickListener {
29 | openLink(requireActivity(), "https://t.me/itaysonlab")
30 | true
31 | }
32 | git.setOnPreferenceClickListener {
33 | openLink(requireActivity(), "https://github.com/iTaysonLab/HomeFeeder/")
34 | true
35 | }
36 | }
37 |
38 | private fun openLink(context: Context, url: String) {
39 | context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/fragments/PreferenceFragment.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.fragments
2 |
3 | import android.os.Build
4 | import android.os.Bundle
5 | import android.widget.Toast
6 | import androidx.preference.*
7 | import ua.itaysonlab.homefeeder.BuildConfig
8 | import ua.itaysonlab.homefeeder.HFApplication
9 | import ua.itaysonlab.homefeeder.R
10 | import ua.itaysonlab.homefeeder.activites.MainActivity
11 | import ua.itaysonlab.homefeeder.fragments.base.FixedPreferencesFragment
12 | import ua.itaysonlab.homefeeder.prefui.HFElementPreview
13 |
14 | class PreferenceFragment : FixedPreferencesFragment() {
15 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
16 | setPreferencesFromResource(R.xml.pref_general, rootKey)
17 |
18 | bindAppearance()
19 | if (BuildConfig.DEBUG) bindDebug()
20 | }
21 |
22 | private fun bindAppearance() {
23 | val summaryProviderInstance = ListPreference.SimpleSummaryProvider.getInstance()
24 |
25 | val theme = findPreference("ovr_theme")!!
26 | val transparency = findPreference("ovr_transparency")!!
27 | val overlayBackground = findPreference("ovr_bg")!!
28 | val cardBackground = findPreference("ovr_card_bg")!!
29 |
30 | val compact = findPreference("ovr_compact")!!
31 | val sysColors = findPreference("ovr_syscolors")!!
32 |
33 | val preview = findPreference("preview")!!
34 |
35 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
36 | sysColors.apply {
37 | isEnabled = false
38 | setSummary(R.string.pref_syscolors_disabled)
39 | }
40 | }
41 |
42 | theme.summaryProvider = summaryProviderInstance
43 | transparency.summaryProvider = summaryProviderInstance
44 | cardBackground.summaryProvider = summaryProviderInstance
45 | overlayBackground.summaryProvider = summaryProviderInstance
46 |
47 | theme.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
48 | preview.applyNewTheme(newValue as String)
49 | HFApplication.bridge.getCallback()?.applyNewTheme(newValue)
50 | true
51 | }
52 |
53 | transparency.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
54 | preview.applyNewTransparency(newValue as String)
55 | HFApplication.bridge.getCallback()?.applyNewTransparency(newValue)
56 | true
57 | }
58 |
59 | compact.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
60 | preview.applyCompact(newValue as Boolean)
61 | HFApplication.bridge.getCallback()?.applyCompactCard(newValue)
62 | true
63 | }
64 |
65 | sysColors.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
66 | HFApplication.bridge.getCallback()?.applySysColors(newValue as Boolean)
67 | true
68 | }
69 |
70 | overlayBackground.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
71 | preview.applyNewOverlayBg(newValue as String)
72 | HFApplication.bridge.getCallback()?.applyNewOverlayBg(newValue)
73 | true
74 | }
75 |
76 | cardBackground.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
77 | preview.applyNewCardBg(newValue as String)
78 | HFApplication.bridge.getCallback()?.applyNewCardBg(newValue)
79 | true
80 | }
81 | }
82 |
83 | private fun bindDebug() {
84 | val debugCategory = PreferenceCategory(preferenceManager.context).apply {
85 | title = "Debug"
86 | isIconSpaceReserved = false
87 | }
88 | val loggingSwitch = SwitchPreference(preferenceManager.context).apply {
89 | key = "HFDebugging"
90 | title = "Extensive logcat printing"
91 | setDefaultValue(false)
92 | isIconSpaceReserved = false
93 | }
94 | val contentLoggingSwitch = SwitchPreference(preferenceManager.context).apply {
95 | key = "HFContentDebugging"
96 | title = "Log notification content"
97 | setDefaultValue(false)
98 | isIconSpaceReserved = false
99 | }
100 | val sendToBridge = Preference(preferenceManager.context).apply {
101 | key = "HFBridgeTest"
102 | title = "Test OverlayBridge"
103 | summary = "Send message \"uiBridgeTest\" to Overlay"
104 | isIconSpaceReserved = false
105 | }
106 | sendToBridge.setOnPreferenceClickListener {
107 | if (HFApplication.bridge.isBridgeAlive()) {
108 | HFApplication.bridge.callServer("uiBridgeTest")
109 | } else {
110 | Toast.makeText(activity, "Bridge is not connected!", Toast.LENGTH_LONG).show()
111 | }
112 | true
113 | }
114 | preferenceScreen.addPreference(debugCategory)
115 | debugCategory.addPreference(loggingSwitch)
116 | debugCategory.addPreference(contentLoggingSwitch)
117 | debugCategory.addPreference(sendToBridge)
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/fragments/base/FixedPreferencesFragment.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.fragments.base
2 |
3 | import android.view.MenuItem
4 | import androidx.preference.*
5 |
6 | abstract class FixedPreferencesFragment : PreferenceFragmentCompat() {
7 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
8 | if (item.itemId == android.R.id.home) {
9 | activity!!.onBackPressed()
10 | return true
11 | }
12 | return super.onOptionsItemSelected(item)
13 | }
14 |
15 | override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
16 | super.setPreferenceScreen(preferenceScreen)
17 | if (preferenceScreen != null) {
18 | val count = preferenceScreen.preferenceCount
19 | for (i in 0 until count) {
20 | val pref = preferenceScreen.getPreference(i)!!
21 | pref.isIconSpaceReserved = false
22 | if (pref is PreferenceCategory) {
23 | val pcount = pref.preferenceCount
24 | for (pi in 0 until pcount) {
25 | pref.getPreference(pi).isIconSpaceReserved = false
26 | }
27 | }
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/kt/KtExtensions.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.kt
2 |
3 | import android.content.Context
4 | import android.graphics.Color
5 | import android.os.Build
6 | import android.os.Bundle
7 | import android.provider.Settings
8 | import android.view.View
9 | import androidx.annotation.ColorInt
10 | import androidx.core.graphics.ColorUtils
11 | import ua.itaysonlab.homefeeder.utils.Logger
12 |
13 | const val LIGHT_BORDER = 0.5f
14 |
15 | fun Int.isLight() = ColorUtils.calculateLuminance(this) > LIGHT_BORDER
16 | fun Int.isDark() = ColorUtils.calculateLuminance(this) < LIGHT_BORDER
17 |
18 | fun Bundle.dump(tag: String) {
19 | keySet().forEach {
20 | val item = get(it)
21 | item ?: return@forEach
22 | Logger.log(tag, "[$it] $item")
23 | }
24 | }
25 |
26 | fun View.setLightFlags() {
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
28 | var flags = systemUiVisibility
29 | flags = flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
30 | systemUiVisibility = flags
31 | }
32 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
33 | var flags = systemUiVisibility
34 | flags = flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
35 | systemUiVisibility = flags
36 | }
37 | }
38 |
39 | fun View.clearLightFlags() {
40 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
41 | var flags = systemUiVisibility
42 | flags = flags xor View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
43 | systemUiVisibility = flags
44 | }
45 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
46 | var flags = systemUiVisibility
47 | flags = flags xor View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
48 | systemUiVisibility = flags
49 | }
50 | }
51 |
52 | @ColorInt
53 | fun Color?.toInt(): Int {
54 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return Color.BLACK
55 | this ?: Color.BLACK
56 | return Color.rgb(this!!.red(), this.green(), this.blue())
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/DrawerOverlayService.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay
2 |
3 | import android.app.Service
4 | import android.content.Intent
5 | import android.os.IBinder
6 |
7 | import com.google.android.apps.gsa.nowoverlayservice.ConfigurationOverlayController
8 | import com.google.android.libraries.gsa.d.a.OverlaysController
9 |
10 | import java.io.FileDescriptor
11 | import java.io.PrintWriter
12 |
13 | class DrawerOverlayService : Service() {
14 | private lateinit var overlaysController: OverlaysController
15 |
16 | override fun onCreate() {
17 | super.onCreate()
18 | this.overlaysController = ConfigurationOverlayController(this)
19 | }
20 |
21 | override fun onDestroy() {
22 | this.overlaysController.onDestroy()
23 | super.onDestroy()
24 | }
25 |
26 | override fun onBind(intent: Intent): IBinder? = this.overlaysController.onBind(intent)
27 |
28 | override fun onUnbind(intent: Intent): Boolean {
29 | this.overlaysController.unUnbind(intent)
30 | return false
31 | }
32 |
33 | /*override fun dump(
34 | fileDescriptor: FileDescriptor,
35 | printWriter: PrintWriter,
36 | strArr: Array
37 | ) {
38 | //this.overlaysController.dump(printWriter)
39 | }*/
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/feed/FeedAdapter.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.feed
2 |
3 | import android.util.SparseIntArray
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.recyclerview.widget.RecyclerView
8 | import ua.itaysonlab.hfsdk.FeedItem
9 | import ua.itaysonlab.hfsdk.FeedItemType
10 | import ua.itaysonlab.homefeeder.R
11 | import ua.itaysonlab.homefeeder.overlay.feed.binders.StoryCardBinder
12 | import ua.itaysonlab.homefeeder.overlay.feed.binders.TextCardBinder
13 | import ua.itaysonlab.homefeeder.overlay.feed.binders.TextCardWithActionsBinder
14 | import ua.itaysonlab.homefeeder.utils.Logger
15 |
16 | class FeedAdapter: RecyclerView.Adapter() {
17 | private var list = listOf()
18 | private lateinit var layoutInflater: LayoutInflater
19 | private var theme: SparseIntArray? = null
20 |
21 | fun replace(new: List) {
22 | list = new
23 | notifyDataSetChanged()
24 | }
25 |
26 | fun append(new: List) {
27 | list = mutableListOf().apply {
28 | addAll(list)
29 | addAll(new)
30 | }
31 |
32 | notifyDataSetChanged()
33 | }
34 |
35 | fun setTheme(theme: SparseIntArray) {
36 | this.theme = theme
37 | notifyDataSetChanged()
38 | }
39 |
40 | override fun getItemCount(): Int {
41 | return list.size
42 | }
43 |
44 | override fun getItemViewType(position: Int): Int {
45 | return (list[position].type.ordinal)
46 | }
47 |
48 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedViewHolder {
49 | if (!::layoutInflater.isInitialized) layoutInflater = LayoutInflater.from(parent.context)
50 |
51 | val layoutResource = when (FeedItemType.values()[viewType]) {
52 | FeedItemType.TEXT_CARD -> R.layout.notification_simple
53 | FeedItemType.TEXT_CARD_ACTIONS -> R.layout.feed_card_text
54 | FeedItemType.STORY_CARD -> R.layout.feed_card_story_large
55 | }
56 |
57 | return FeedViewHolder(viewType, layoutInflater.inflate(layoutResource, parent, false))
58 | }
59 |
60 | override fun onBindViewHolder(holder: FeedViewHolder, position: Int) {
61 | val item = list[position]
62 | when (FeedItemType.values()[holder.type]) {
63 | FeedItemType.TEXT_CARD -> TextCardBinder.bind(theme, item, holder.itemView)
64 | FeedItemType.TEXT_CARD_ACTIONS -> TextCardWithActionsBinder.bind(theme, item, holder.itemView)
65 | FeedItemType.STORY_CARD -> StoryCardBinder.bind(theme, item, holder.itemView)
66 | }
67 | }
68 |
69 | inner class FeedViewHolder(val type: Int, itemView: View): RecyclerView.ViewHolder(itemView)
70 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/feed/binders/FeedBinder.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.feed.binders
2 |
3 | import android.util.SparseIntArray
4 | import android.view.View
5 | import ua.itaysonlab.hfsdk.FeedItem
6 |
7 | interface FeedBinder {
8 | fun bind(theme: SparseIntArray?, item: FeedItem, view: View)
9 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/feed/binders/StoryCardBinder.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.feed.binders
2 |
3 | import android.content.Intent
4 | import android.net.Uri
5 | import android.text.Html
6 | import android.util.SparseIntArray
7 | import android.view.View
8 | import coil.load
9 | import ua.itaysonlab.hfsdk.FeedItem
10 | import ua.itaysonlab.hfsdk.content.StoryCardContent
11 | import ua.itaysonlab.homefeeder.databinding.FeedCardStoryLargeBinding
12 | import ua.itaysonlab.homefeeder.kt.isDark
13 | import ua.itaysonlab.homefeeder.theming.Theming
14 |
15 | object StoryCardBinder: FeedBinder {
16 | override fun bind(theme: SparseIntArray?, item: FeedItem, view: View) {
17 | val content = item.content as StoryCardContent
18 | val binding = FeedCardStoryLargeBinding.bind(view)
19 |
20 | binding.storyTitle.text = content.title
21 | binding.storySource.text = content.source.title
22 |
23 | if (content.text.isEmpty()) {
24 | binding.storyDesc.visibility = View.GONE
25 | } else {
26 | binding.storyDesc.text = Html.fromHtml(content.text).toString()
27 | }
28 |
29 | binding.storyPic.load(content.background_url)
30 |
31 | theme ?: return
32 | binding.storyDimmer.setBackgroundColor(theme.get(Theming.Colors.CARD_BG.ordinal))
33 | val themeCard = if (theme.get(Theming.Colors.CARD_BG.ordinal).isDark()) Theming.defaultDarkThemeColors else Theming.defaultLightThemeColors
34 | binding.storyTitle.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_PRIMARY.ordinal))
35 | binding.storySource.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_SECONDARY.ordinal))
36 | binding.storyDesc.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_SECONDARY.ordinal))
37 |
38 | binding.root.setOnClickListener {
39 | view.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(content.link)))
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/feed/binders/TextCardBinder.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.feed.binders
2 |
3 | import android.util.SparseIntArray
4 | import android.view.View
5 | import ua.itaysonlab.hfsdk.FeedItem
6 | import ua.itaysonlab.hfsdk.content.TextCardContent
7 | import ua.itaysonlab.homefeeder.HFApplication
8 | import ua.itaysonlab.homefeeder.databinding.NotificationGenericContentBinding
9 | import ua.itaysonlab.homefeeder.utils.RelativeTimeHelper
10 |
11 | object TextCardBinder: FeedBinder {
12 | override fun bind(theme: SparseIntArray?, item: FeedItem, view: View) {
13 | val content = item.content as TextCardContent
14 | val binding = NotificationGenericContentBinding.bind(view)
15 |
16 | binding.notTitle.text = content.title
17 | binding.notTitle.visibility = if (content.title.isEmpty()) {
18 | View.GONE
19 | } else View.VISIBLE
20 |
21 | binding.notText.text = content.text
22 | binding.notText.visibility = if (content.text.isEmpty()) {
23 | View.GONE
24 | } else View.VISIBLE
25 |
26 | binding.notAppSubtitle.text = content.subtitle
27 | binding.notAppSubtitle.visibility = if (content.subtitle == null) {
28 | View.GONE
29 | } else View.VISIBLE
30 |
31 | binding.notAppName.text = item.title
32 | binding.notAppIcon.visibility = View.GONE
33 | binding.notAppDate.text = RelativeTimeHelper.getDateFormattedRelative(HFApplication.instance, (item.time/1000) - 1000)
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/feed/binders/TextCardWithActionsBinder.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.feed.binders
2 |
3 | import android.util.SparseIntArray
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import ua.itaysonlab.hfsdk.FeedItem
9 | import ua.itaysonlab.hfsdk.content.TextCardContent
10 | import ua.itaysonlab.homefeeder.R
11 |
12 | object TextCardWithActionsBinder: FeedBinder {
13 | override fun bind(theme: SparseIntArray?, item: FeedItem, view: View) {
14 | TextCardBinder.bind(theme, item, view)
15 | val valley = view.findViewById(R.id.button_valley_2)
16 | valley.removeAllViews()
17 | (item.content as TextCardContent).actions?.forEach {
18 | valley.addView(LayoutInflater.from(view.context).inflate(R.layout.feed_card_action, view as ViewGroup, false).apply {
19 | (this as TextView).text = it.title
20 | })
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/launcherapi/LauncherAPI.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.launcherapi
2 |
3 | import android.graphics.Color
4 | import android.os.Bundle
5 | import androidx.annotation.ColorInt
6 | import ua.itaysonlab.homefeeder.kt.dump
7 | import ua.itaysonlab.homefeeder.preferences.HFPreferences
8 |
9 | /**
10 | * A class which parses data from launcher's options [android.os.Bundle].
11 | * */
12 | class LauncherAPI(bundle: Bundle = Bundle()) {
13 | companion object {
14 | const val LOG_TAG = "LauncherAPI"
15 |
16 | const val DARK_THEME_KEY = "is_background_dark"
17 | const val BG_HINT_KEY = "background_color_hint"
18 | const val BG_SECONDARY_HINT_KEY = "background_secondary_color_hint"
19 | const val BG_TERTIARY_HINT_KEY = "background_tertiary_color_hint"
20 | }
21 |
22 | /**
23 | * If the wallpaper is dark enough.
24 | * Available on almost every launcher
25 | */
26 | var darkTheme = false
27 |
28 | /**
29 | * Primary wallpaper color.
30 | * Seems like it's available only on Lawnchair.
31 | * On Shade, it returns applied theme color.
32 | */
33 | @ColorInt
34 | var backgroundColorHint = Color.BLACK
35 |
36 | /**
37 | * Secondary wallpaper color.
38 | * Only on Lawnchair (and Librechair too).
39 | */
40 | @ColorInt
41 | var backgroundColorHintSecondary = Color.BLACK
42 |
43 | /**
44 | * Tertiary wallpaper color.
45 | * Available only on Librechair.
46 | */
47 | @ColorInt
48 | var backgroundColorHintTertiary = Color.BLACK
49 |
50 | init {
51 | if (HFPreferences.contentDebugging) {
52 | bundle.dump(LOG_TAG)
53 | }
54 |
55 | darkTheme = bundle.getBoolean(DARK_THEME_KEY, true)
56 | backgroundColorHint = bundle.getInt(BG_HINT_KEY, Color.BLACK)
57 | backgroundColorHintSecondary = bundle.getInt(BG_SECONDARY_HINT_KEY, Color.BLACK)
58 | backgroundColorHintTertiary = bundle.getInt(BG_TERTIARY_HINT_KEY, Color.BLACK)
59 | }
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/overlay/launcherapi/OverlayThemeHolder.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.overlay.launcherapi
2 |
3 | import android.annotation.TargetApi
4 | import android.app.WallpaperManager
5 | import android.content.Context
6 | import android.graphics.Color
7 | import android.os.Build
8 | import android.util.SparseIntArray
9 | import androidx.annotation.ColorInt
10 | import androidx.core.content.ContextCompat
11 | import ua.itaysonlab.homefeeder.HFApplication
12 | import ua.itaysonlab.homefeeder.R
13 | import ua.itaysonlab.homefeeder.kt.clearLightFlags
14 | import ua.itaysonlab.homefeeder.kt.isLight
15 | import ua.itaysonlab.homefeeder.kt.toInt
16 | import ua.itaysonlab.homefeeder.overlay.OverlayKt
17 | import ua.itaysonlab.homefeeder.preferences.HFPreferences
18 | import ua.itaysonlab.homefeeder.theming.Theming
19 | import ua.itaysonlab.homefeeder.utils.Logger
20 |
21 | /**
22 | * A class which manages overlay styling.
23 | * */
24 | class OverlayThemeHolder(private val context: Context, private val overlay: OverlayKt) {
25 | /**
26 | * Current theme colors mapping
27 | */
28 | var currentTheme = Theming.defaultDarkThemeColors
29 |
30 | /**
31 | * Card background
32 | */
33 | var cardBgPref = HFPreferences.cardBackground
34 |
35 | /**
36 | * Overlay background
37 | */
38 | var overlayBgPref = HFPreferences.overlayBackground
39 |
40 | /**
41 | * Overlay transparency
42 | */
43 | var transparencyBgPref = HFPreferences.overlayTransparency
44 |
45 | /**
46 | * If we should apply light statusbar/navbar
47 | */
48 | var shouldUseSN = false
49 |
50 | /**
51 | * If we are applied light statusbar/navbar
52 | */
53 | var isSNApplied = false
54 |
55 | /**
56 | * If we are using system colors instead of [LauncherAPI]
57 | */
58 | var systemColors = false
59 |
60 | /**
61 | * Parses [cardBgPref] into color integer
62 | */
63 | private val cardBackground: Int get() = when (cardBgPref) {
64 | "white" -> ContextCompat.getColor(context, R.color.card_bg)
65 | "dark" -> ContextCompat.getColor(context, R.color.card_bg_dark)
66 | "launcher_primary" -> if (HFPreferences.systemColors) primaryWallColor() else overlay.apiInstance.backgroundColorHint
67 | "launcher_secondary" -> if (HFPreferences.systemColors) secondaryWallColor() else overlay.apiInstance.backgroundColorHintSecondary
68 | "launcher_tertiary" -> if (HFPreferences.systemColors) tertiaryWallColor() else overlay.apiInstance.backgroundColorHintTertiary
69 | else -> Color.BLACK
70 | }
71 |
72 | /**
73 | * Parses [overlayBgPref] into color integer
74 | */
75 | private val overlayBackground: Int get() = when (overlayBgPref) {
76 | "white" -> Color.WHITE
77 | "dark" -> ContextCompat.getColor(context, R.color.bg_dark)
78 | "launcher_primary" -> if (HFPreferences.systemColors) primaryWallColor() else overlay.apiInstance.backgroundColorHint
79 | "launcher_secondary" -> if (HFPreferences.systemColors) secondaryWallColor() else overlay.apiInstance.backgroundColorHintSecondary
80 | "launcher_tertiary" -> if (HFPreferences.systemColors) tertiaryWallColor() else overlay.apiInstance.backgroundColorHintTertiary
81 | else -> Color.BLACK
82 | }
83 |
84 | /**
85 | * If [transparencyBgPref] is fully transparent
86 | */
87 | val isTransparentBg get() = transparencyBgPref == "transparent"
88 |
89 | /**
90 | * Parses scroll alpha to match theme
91 | */
92 | fun getScrollAlpha(alpha: Float): Float {
93 | return if (transparencyBgPref == "half" && alpha > 0.5f) {
94 | 0.5f
95 | } else if (transparencyBgPref == "less_half" && alpha > 0.25f) {
96 | 0.25f
97 | } else if (transparencyBgPref == "more_half" && alpha > 0.75f) {
98 | 0.75f
99 | } else alpha
100 | }
101 |
102 | /**
103 | * Replaces the color mapping ([currentTheme]) with config-specified values
104 | */
105 | fun setTheme(theme: SparseIntArray) {
106 | currentTheme = theme
107 |
108 | shouldUseSN = if (overlayBgPref != "theme") {
109 | currentTheme.put(Theming.Colors.OVERLAY_BG.ordinal, overlayBackground)
110 | overlayBackground.isLight()
111 | } else {
112 | currentTheme.get(Theming.Colors.IS_LIGHT.ordinal) == 1
113 | }
114 |
115 | if (!shouldUseSN && isSNApplied) {
116 | isSNApplied = false
117 | overlay.window.decorView.clearLightFlags()
118 | }
119 |
120 | if (cardBgPref != "theme") {
121 | currentTheme.put(Theming.Colors.CARD_BG.ordinal, cardBackground)
122 | }
123 |
124 | Logger.log("OTH", currentTheme.toString())
125 | }
126 |
127 | companion object {
128 | @ColorInt
129 | @TargetApi(Build.VERSION_CODES.O_MR1)
130 | fun primaryWallColor(): Int {
131 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return Color.BLACK
132 | val wc = WallpaperManager.getInstance(HFApplication.instance).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
133 | wc ?: Color.BLACK
134 | return wc!!.primaryColor.toInt()
135 | }
136 |
137 | @ColorInt
138 | @TargetApi(Build.VERSION_CODES.O_MR1)
139 | fun secondaryWallColor(): Int {
140 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return Color.BLACK
141 | val wc = WallpaperManager.getInstance(HFApplication.instance).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
142 | wc ?: Color.BLACK
143 | return wc!!.secondaryColor.toInt()
144 | }
145 |
146 | @ColorInt
147 | @TargetApi(Build.VERSION_CODES.O_MR1)
148 | fun tertiaryWallColor(): Int {
149 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return Color.BLACK
150 | val wc = WallpaperManager.getInstance(HFApplication.instance).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
151 | wc ?: Color.BLACK
152 | wc?.tertiaryColor ?: Color.BLACK
153 | return wc!!.tertiaryColor.toInt()
154 | }
155 | }
156 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/pluginsystem/PluginConnector.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.pluginsystem
2 |
3 | import android.app.Service
4 | import android.content.ComponentName
5 | import android.content.Intent
6 | import android.content.ServiceConnection
7 | import android.os.Handler
8 | import android.os.IBinder
9 | import android.os.Looper
10 | import androidx.core.os.bundleOf
11 | import androidx.recyclerview.widget.RecyclerView
12 | import ua.itaysonlab.hfsdk.FeedCategory
13 | import ua.itaysonlab.hfsdk.FeedItem
14 | import ua.itaysonlab.hfsdk.IFeedInterface
15 | import ua.itaysonlab.hfsdk.IFeedInterfaceCallback
16 | import ua.itaysonlab.homefeeder.HFApplication
17 | import ua.itaysonlab.homefeeder.preferences.HFPluginPreferences
18 | import ua.itaysonlab.homefeeder.utils.Logger
19 |
20 | object PluginConnector {
21 | const val TAG = "PluginConnector"
22 | private var hasInitialized = false
23 |
24 | private var interfaces = hashMapOf()
25 | private var callbacks = hashMapOf()
26 |
27 | private var index = 0
28 | private var serviceSize = 0
29 |
30 | private val handler = Handler(Looper.getMainLooper())
31 |
32 | private val serviceConnection: ServiceConnection = object : ServiceConnection {
33 | override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
34 | Logger.log(TAG, "Connected to service ${componentName.packageName} / ${componentName.className}")
35 | interfaces[componentName.packageName] = IFeedInterface.Stub.asInterface(iBinder)
36 | interfaces[componentName.packageName]!!.getFeed(callbacks[componentName.packageName], 0, "default", null)
37 | }
38 |
39 | override fun onServiceDisconnected(componentName: ComponentName) {
40 | Logger.log(TAG, "Disconnected from service ${componentName.packageName} / ${componentName.className}")
41 | interfaces[componentName.packageName] = null
42 | }
43 | }
44 |
45 | private fun connectTo(pkg: String) {
46 | Logger.log(TAG, "Connecting to: $pkg")
47 | val intent = Intent("$pkg.HFPluginService")
48 | intent.action = PluginFetcher.INTENT_ACTION_SERVICE
49 | intent.setPackage(pkg)
50 | HFApplication.instance.bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE)
51 | }
52 |
53 | fun clear() {
54 | index = 0
55 | serviceSize = 0
56 | interfaces.clear()
57 | callbacks.clear()
58 | hasInitialized = false
59 | }
60 |
61 | fun getFeedAsItLoads(page: Int, onNewFeed: (List) -> Unit, onLoadFinished: () -> Unit) {
62 | Logger.log(TAG, "getFeedAsItLoads")
63 |
64 | val stub = object: IFeedInterfaceCallback.Stub() {
65 | override fun onCategoriesReceive(categories: MutableList?) {
66 |
67 | }
68 |
69 | override fun onFeedReceive(feed: MutableList?) {
70 | feed ?: return
71 |
72 | Logger.log(TAG, "Received feed: $feed")
73 |
74 | onNewFeed(feed)
75 |
76 | index++
77 | if (index >= serviceSize) {
78 | Logger.log(TAG, "Finished chain!")
79 | handler.post {
80 | onLoadFinished()
81 | }
82 | }
83 | }
84 | }
85 |
86 | if (hasInitialized) {
87 | index = 0
88 | interfaces.forEach {
89 | it.value?.getFeed(stub, page, "default", null)
90 | }
91 | return
92 | }
93 |
94 | chainLoad(stub)
95 | hasInitialized = true
96 | }
97 |
98 | private fun chainLoad(cb: IFeedInterfaceCallback) {
99 | index = 0
100 | serviceSize = HFPluginPreferences.enabledList.size
101 | HFPluginPreferences.enabledList.forEach {
102 | callbacks[it] = cb
103 | connectTo(it)
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/pluginsystem/PluginFetcher.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.pluginsystem
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.content.pm.PackageManager
6 | import ua.itaysonlab.homefeeder.preferences.HFPreferences
7 | import ua.itaysonlab.homefeeder.utils.Logger
8 |
9 | object PluginFetcher {
10 | // List of available packages.
11 | val availablePlugins = hashMapOf()
12 |
13 | // Required part for AIDL connection.
14 | const val INTENT_ACTION_SERVICE = "ua.itaysonlab.hfsdk.HOMEFEEDER_PLUGIN_SERVICE"
15 |
16 | // Plugin settings action
17 | const val INTENT_ACTION_SETTINGS = "ua.itaysonlab.hfsdk.HOMEFEEDER_PLUGIN_ENTRYPOINT"
18 |
19 | // Metadata value acting for SDK version.
20 | private const val METADATA_SDK_VERSION = "HF_PluginSDK_Version"
21 |
22 | private const val METADATA_NAME = "HF_Plugin_Name"
23 | private const val METADATA_DESCRIPTION = "HF_Plugin_Description"
24 | private const val METADATA_AUTHOR = "HF_Plugin_Author"
25 | private const val METADATA_HAS_SETTINGS = "HF_Plugin_HasSettingsActivity"
26 |
27 | fun init(ctx: Context) {
28 | fillListBy(ctx.packageManager)
29 | }
30 |
31 | // Fill list of suitable packages.
32 | private fun fillListBy(packageManager: PackageManager) {
33 | availablePlugins.clear()
34 |
35 | val hasService = packageManager.queryIntentServices(
36 | Intent(INTENT_ACTION_SERVICE),
37 | PackageManager.GET_META_DATA
38 | ).map {
39 | Pair(it.serviceInfo.packageName, it.serviceInfo.metaData)
40 | }
41 |
42 | if (HFPreferences.debugging) {
43 | Logger.log("PluginFetcher", "Packages that has service: $hasService")
44 | }
45 |
46 | hasService.forEach {
47 | //Logger.log("PluginFetcher", "$it")
48 | availablePlugins[it.first] = SlimPluginInfo(
49 | it.first,
50 | hasPluginSettings = it.second.getBoolean(METADATA_HAS_SETTINGS),
51 | sdkVersion = it.second.getInt(METADATA_SDK_VERSION),
52 | title = it.second.getString(METADATA_NAME, ""),
53 | description = it.second.getString(METADATA_DESCRIPTION, ""),
54 | author = it.second.getString(METADATA_AUTHOR, "")
55 | )
56 | }
57 | }
58 |
59 | data class SlimPluginInfo(
60 | val pkg: String,
61 | val hasPluginSettings: Boolean,
62 | val sdkVersion: Int,
63 | val title: String,
64 | val description: String,
65 | val author: String
66 | )
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/preferences/HFPluginPreferences.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.preferences
2 |
3 | import ua.itaysonlab.homefeeder.utils.PreferenceHelper
4 |
5 | object HFPluginPreferences {
6 | private const val KEY = "HFEnabledPlugins"
7 |
8 | val enabledList get() = PreferenceHelper.getSet(KEY)
9 |
10 | fun add(pkg: String) {
11 | PreferenceHelper.setSet(KEY, enabledList.apply {
12 | add(pkg)
13 | })
14 | }
15 |
16 | fun remove(pkg: String) {
17 | PreferenceHelper.setSet(KEY, enabledList.apply {
18 | remove(pkg)
19 | })
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/preferences/HFPreferences.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.preferences
2 |
3 | import ua.itaysonlab.homefeeder.utils.PreferenceHelper
4 |
5 | object HFPreferences {
6 | val debugging get() = PreferenceHelper.get("HFDebugging", false)
7 | val contentDebugging get() = PreferenceHelper.get("HFContentDebugging", false)
8 | val overlayCompact get() = PreferenceHelper.get("ovr_compact", false)
9 | val systemColors get() = PreferenceHelper.get("ovr_syscolors", false)
10 | val overlayTheme get() = PreferenceHelper.get("ovr_theme", "auto_launcher")
11 | val overlayTransparency get() = PreferenceHelper.get("ovr_transparency", "non_transparent")
12 | val overlayBackground get() = PreferenceHelper.get("ovr_bg", "theme")
13 | val cardBackground get() = PreferenceHelper.get("ovr_card_bg", "theme")
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/theming/Theming.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.theming
2 |
3 | import android.content.Context
4 | import android.content.res.Configuration
5 | import android.util.SparseIntArray
6 | import androidx.core.content.ContextCompat
7 | import ua.itaysonlab.homefeeder.HFApplication
8 | import ua.itaysonlab.homefeeder.R
9 |
10 | object Theming {
11 | val defaultLightThemeColors = createLightTheme()
12 | val defaultDarkThemeColors = createDarkTheme()
13 |
14 | private fun createLightTheme(): SparseIntArray {
15 | return SparseIntArray().apply {
16 | addBasicThings(this)
17 | put(Colors.CARD_BG.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.card_bg))
18 | put(Colors.TEXT_COLOR_PRIMARY.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.text_color_primary))
19 | put(Colors.TEXT_COLOR_SECONDARY.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.text_color_secondary))
20 | put(Colors.OVERLAY_BG.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.bg_overlay))
21 | put(Colors.IS_LIGHT.ordinal, 1)
22 | }
23 | }
24 |
25 | private fun createDarkTheme(): SparseIntArray {
26 | return SparseIntArray().apply {
27 | addBasicThings(this)
28 | put(Colors.CARD_BG.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.card_bg_dark))
29 | put(Colors.TEXT_COLOR_PRIMARY.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.text_color_primary_dark))
30 | put(Colors.TEXT_COLOR_SECONDARY.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.text_color_secondary_dark))
31 | put(Colors.OVERLAY_BG.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.bg_dark))
32 | put(Colors.IS_LIGHT.ordinal, 0)
33 | }
34 | }
35 |
36 | private fun addBasicThings(array: SparseIntArray): SparseIntArray {
37 | return array.apply {
38 | put(Colors.ACCENT_COLOR.ordinal, ContextCompat.getColor(HFApplication.instance, R.color.globalAccent))
39 | }
40 | }
41 |
42 | fun getThemeBySystem(ctx: Context): SparseIntArray {
43 | return if (ctx.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES) createDarkTheme() else createLightTheme()
44 | }
45 |
46 | enum class Colors {
47 | CARD_BG,
48 | TEXT_COLOR_PRIMARY,
49 | TEXT_COLOR_SECONDARY,
50 | ACCENT_COLOR,
51 | OVERLAY_BG,
52 | IS_LIGHT
53 | }
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/utils/Logger.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.utils
2 |
3 | import android.util.Log
4 | import ua.itaysonlab.homefeeder.BuildConfig
5 |
6 | /**
7 | * This class wraps [android.util.Log].
8 | */
9 | object Logger {
10 | fun log(tag: String, msg: String) {
11 | if (BuildConfig.DEBUG) Log.d("HF:$tag", msg)
12 | }
13 |
14 | fun w(tag: String, msg: String) {
15 | Log.w(tag, msg)
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/utils/OverlayBridge.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.utils
2 |
3 | class OverlayBridge {
4 | private var callback: OverlayBridgeCallback? = null
5 |
6 | fun callServer(action: String) {
7 | if (isBridgeAlive()) callback!!.onClientMessage(action)
8 | }
9 |
10 | fun getCallback(): OverlayBridgeCallback? {
11 | return callback
12 | }
13 |
14 | fun setCallback(callback: OverlayBridgeCallback?) {
15 | this.callback = callback
16 | }
17 |
18 | fun isBridgeAlive() = callback !== null
19 |
20 | interface OverlayBridgeCallback {
21 | fun applyNewTheme(value: String)
22 | fun applyNewCardBg(value: String)
23 | fun applyNewOverlayBg(value: String)
24 | fun applyCompactCard(value: Boolean)
25 | fun applySysColors(value: Boolean)
26 | fun applyNewTransparency(value: String)
27 |
28 | fun onClientMessage(action: String)
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/utils/PreferenceHelper.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.utils
2 |
3 | import android.content.SharedPreferences
4 | import androidx.preference.PreferenceManager
5 | import ua.itaysonlab.homefeeder.HFApplication
6 |
7 | object PreferenceHelper {
8 | private val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(HFApplication.instance)
9 |
10 | fun get(key: String, default: Boolean): Boolean {
11 | return prefs.getBoolean(key, default)
12 | }
13 |
14 | fun get(key: String, default: String): String {
15 | return prefs.getString(key, default)!!
16 | }
17 |
18 | fun getSet(key: String): MutableSet {
19 | return prefs.getStringSet(key, mutableSetOf())!!
20 | }
21 |
22 | fun setSet(key: String, set: MutableSet) {
23 | Logger.log("PH", "Putting $set to $key")
24 | prefs.edit().apply {
25 | remove(key)
26 | commit()
27 | putStringSet(key, set)
28 | commit()
29 | }
30 | }
31 |
32 | fun get(key: String, default: Int): Int {
33 | return prefs.getInt(key, default)
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/homefeeder/utils/RelativeTimeHelper.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.homefeeder.utils
2 |
3 | import android.content.Context
4 | import ua.itaysonlab.homefeeder.R
5 | import java.util.Calendar
6 | import java.util.Locale
7 | import kotlin.math.min
8 |
9 | object RelativeTimeHelper {
10 | private val calendar: Calendar
11 | get() = Calendar.getInstance()
12 |
13 | private val currentTime: Long
14 | get() = System.currentTimeMillis() / 1000
15 |
16 | private fun getAbsoluteDate(context: Context, i: Long): String {
17 | val resources = context.resources
18 | val j = i * 1000
19 | val calendar = calendar
20 | val i2 = calendar.get(Calendar.YEAR)
21 | calendar.set(Calendar.MINUTE, 0)
22 | calendar.set(Calendar.HOUR_OF_DAY, 0)
23 | calendar.set(Calendar.SECOND, 0)
24 | calendar.set(Calendar.MILLISECOND, 0)
25 | val timeInMillis = calendar.timeInMillis
26 | var j2 = 86400000.toLong()
27 | var j3 = timeInMillis + j2
28 | var j4 = j3 + j2
29 | j2 = timeInMillis - j2
30 | calendar.timeInMillis = j
31 | j4--
32 | val locale: Locale
33 | val str: String
34 | var format: String
35 | if (j in j3..j4) {
36 | locale = Locale.ENGLISH
37 | str = "%s %s %d:%02d"
38 | val tomorrow = resources.getString(R.string.tomorrow)
39 | val at = resources.getString(if (calendar.get(Calendar.HOUR_OF_DAY) == 1) R.string.date_at_1am else R.string.date_at)
40 | val hourOfDay = calendar.get(Calendar.HOUR_OF_DAY)
41 | val minute = calendar.get(Calendar.MINUTE)
42 | format = String.format(locale, str, tomorrow, at, hourOfDay, minute)
43 | return format
44 | }
45 | j3--
46 | if (j in timeInMillis..j3) {
47 | locale = Locale.ENGLISH
48 | str = "%s %s %d:%02d"
49 | val today = resources.getString(R.string.today)
50 | val at = resources.getString(if (calendar.get(Calendar.HOUR_OF_DAY) == 1) R.string.date_at_1am else R.string.date_at)
51 | val hourOfDay = calendar.get(Calendar.HOUR_OF_DAY)
52 | val minute = calendar.get(Calendar.MINUTE)
53 | format = String.format(locale, str, today, at, hourOfDay, minute)
54 | return format
55 | } else if (j < j2 || j >= timeInMillis) {
56 | val string: String = if (calendar.get(Calendar.YEAR) != i2) {
57 | resources.getString(R.string.date_format_day_month_year, calendar.get(Calendar.DAY_OF_MONTH), resources.getStringArray(R.array.date_shortmonths)[min(calendar.get(2), Calendar.HOUR_OF_DAY)], calendar.get(Calendar.YEAR))
58 | } else {
59 | resources.getString(R.string.date_format_day_month, calendar.get(Calendar.DAY_OF_MONTH), resources.getStringArray(R.array.date_shortmonths)[min(calendar.get(2), Calendar.HOUR_OF_DAY)])
60 | }
61 | val stringBuilder = StringBuilder()
62 | stringBuilder.append(string)
63 | locale = Locale.ENGLISH
64 | val str2 = " %s %d:%02d"
65 | val at = resources.getString(if (calendar.get(Calendar.HOUR_OF_DAY) == 1) R.string.date_at_1am else R.string.date_at)
66 | val hourOfDay = calendar.get(Calendar.HOUR_OF_DAY)
67 | val minute = calendar.get(Calendar.MINUTE)
68 | format = String.format(locale, str2, at, hourOfDay, minute)
69 | stringBuilder.append(format)
70 | format = stringBuilder.toString()
71 | return format
72 | } else {
73 | locale = Locale.ENGLISH
74 | str = "%s %s %d:%02d"
75 | val yesterday = resources.getString(R.string.yesterday)
76 | val at = resources.getString(if (calendar.get(Calendar.HOUR_OF_DAY) == 1) R.string.date_at_1am else R.string.date_at)
77 | val hourOfDay = calendar.get(Calendar.HOUR_OF_DAY)
78 | val minute = calendar.get(Calendar.MINUTE)
79 | format = String.format(locale, str, yesterday, at, hourOfDay, minute)
80 | return format
81 | }
82 | }
83 |
84 | /**
85 | * @param context - Context to use with resources
86 | * @param i - Time in seconds (Unix timestamp)
87 | * @return Time relative to this
88 | */
89 | fun getDateFormattedRelative(context: Context, i: Long): String {
90 | val resources = context.resources
91 | val currentTime = currentTime - i
92 | if (currentTime >= 14400 || currentTime < 0) {
93 | return getAbsoluteDate(context, i)
94 | }
95 | return when {
96 | currentTime >= 10800 -> {
97 | resources.getStringArray(R.array.date_ago_hrs)[2]
98 | }
99 | currentTime >= 7200 -> {
100 | resources.getStringArray(R.array.date_ago_hrs)[1]
101 | }
102 | currentTime >= 3600 -> {
103 | resources.getStringArray(R.array.date_ago_hrs)[0]
104 | }
105 | currentTime >= 60 -> {
106 | resources.getQuantityString(R.plurals.date_ago_mins, (currentTime / 60).toInt(), (currentTime / 60).toInt())
107 | }
108 | currentTime <= 10 -> {
109 | resources.getString(R.string.date_ago_now)
110 | }
111 | else -> {
112 | resources.getQuantityString(R.plurals.date_ago_secs, currentTime.toInt(), currentTime.toInt())
113 | }
114 | }
115 | }
116 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/ActionAdapter.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.content.Context
4 | import android.view.LayoutInflater
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import ua.itaysonlab.homefeeder.R
8 |
9 | class ActionAdapter(private val e: Context, private val f: ActionStyle): RecyclerView.Adapter() {
10 | private val f2972a = LayoutInflater.from(this.e)
11 | private var c: List = listOf()
12 | private var d: ((PopupItem) -> Unit)? = null
13 |
14 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ActionVh {
15 | return ActionVh(f2972a.inflate(R.layout.vklib_actionslistview_entry, parent, false), this.f)
16 | }
17 |
18 | override fun getItemCount(): Int {
19 | return this.c.size
20 | }
21 |
22 | fun a(i: Int): PopupItem {
23 | return this.c[i]
24 | }
25 |
26 | override fun onBindViewHolder(holder: ActionVh, position: Int) {
27 | holder.a(d!!)
28 | holder.a(this.c[position])
29 | }
30 |
31 | override fun onViewRecycled(holder: ActionVh) {
32 | super.onViewRecycled(holder)
33 | holder.a(null)
34 | }
35 |
36 | fun a(): ((PopupItem) -> Unit)? {
37 | return this.d
38 | }
39 |
40 | fun a(cVar: (PopupItem) -> Unit) {
41 | this.d = cVar
42 | }
43 |
44 | fun a(list: List) {
45 | this.c = list
46 | notifyDataSetChanged()
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/ActionDivider.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Paint
5 | import android.graphics.Rect
6 | import android.view.View
7 | import androidx.recyclerview.widget.RecyclerView
8 |
9 | class ActionDivider(private val style: DividerStyle): RecyclerView.ItemDecoration() {
10 | private val f2974a = Paint()
11 | private val b = Rect()
12 |
13 | init {
14 | this.f2974a.color = style.dividerColor
15 | this.f2974a.isAntiAlias = false
16 | this.f2974a.isDither = false
17 | }
18 |
19 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
20 | if (a(parent, view)) {
21 | outRect.bottom = style.dividerHeight
22 | }
23 | }
24 |
25 | override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
26 | super.onDraw(c, parent, state)
27 | if (parent.childCount != 0) {
28 | val paddingLeft = parent.paddingLeft
29 | val measuredWidth = parent.measuredWidth - parent.paddingRight
30 |
31 | for (i in 0 until parent.childCount) {
32 | val childAt = parent.getChildAt(i)
33 | if (a(parent, childAt)) {
34 | val bottom = childAt.bottom + ((this.style.dividerHeight / 2) - (this.style.dividerSize / 2))
35 | this.b.set(paddingLeft, bottom, measuredWidth, this.style.dividerSize + bottom)
36 | c.drawRect(this.b, this.f2974a)
37 | }
38 | }
39 | }
40 | }
41 |
42 | companion object {
43 | fun a(recyclerView: RecyclerView, view: View): Boolean {
44 | val cap = recyclerView.getChildAdapterPosition(view)
45 | if (cap == -1) return false
46 | val adapter = recyclerView.adapter as ActionAdapter
47 | if (cap == adapter.itemCount - 1) return false
48 | if (adapter.a(cap).group != adapter.a(cap + 1).group) return true
49 | return false
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/ActionStyle.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.graphics.drawable.Drawable
4 | import androidx.annotation.UiThread
5 |
6 | @UiThread
7 | data class ActionStyle(
8 | var optionBackground: Drawable?,
9 | var paddingStart: Int,
10 | var paddingEnd: Int,
11 | var iconSpace: Int,
12 | var iconTint: Int?,
13 | var textSize: Int,
14 | var textColor: Int
15 | )
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/ActionVh.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.graphics.PorterDuff
4 | import android.graphics.PorterDuffColorFilter
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.ImageView
8 | import android.widget.TextView
9 | import androidx.recyclerview.widget.RecyclerView
10 | import ua.itaysonlab.homefeeder.R
11 |
12 | class ActionVh(private val f: View, private val g: ActionStyle): RecyclerView.ViewHolder(f) {
13 | private val b: ImageView = this.f.findViewById(R.id.icon)
14 | private val c: TextView = this.f.findViewById(R.id.label)
15 | private var d: PopupItem? = null
16 | private var e: ((PopupItem) -> Unit)? = null
17 |
18 | init {
19 | //this.f.background = this.g.optionBackground
20 | this.f.setPaddingRelative(this.g.paddingStart, 0, this.g.paddingEnd, 0)
21 | this.f.setOnClickListener {
22 | if (d != null && e != null) {
23 | e?.invoke(d!!)
24 | }
25 | }
26 | if (this.g.iconTint != null) {
27 | this.b.colorFilter = PorterDuffColorFilter(this.g.iconTint!!, PorterDuff.Mode.SRC_IN)
28 | }
29 | this.c.setTextSize(0, this.g.textSize.toFloat())
30 | this.c.setTextColor(this.g.textColor)
31 | this.c.layoutParams = (this.c.layoutParams as ViewGroup.MarginLayoutParams).apply {
32 | marginStart = g.iconSpace
33 | }
34 | }
35 |
36 | fun a(): ((PopupItem) -> Unit)? {
37 | return this.e
38 | }
39 |
40 | fun a(cVar: ((PopupItem) -> Unit)?) {
41 | this.e = cVar
42 | }
43 |
44 | fun a(aVar: PopupItem) {
45 | this.d = aVar
46 | this.b.setImageResource(aVar.icon)
47 | this.c.setText(aVar.title)
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/DialogActionsVcByPopup.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.res.Resources
5 | import android.graphics.Rect
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import androidx.annotation.UiThread
9 | import ua.itaysonlab.homefeeder.R
10 | import kotlin.math.ceil
11 |
12 | @UiThread
13 | class DialogActionsVcByPopup(private val d: View) {
14 | private var b: (() -> Unit)? = null
15 | private var c: PopupWindowImpl? = null
16 | private fun a(): Boolean = this.c != null
17 |
18 | private fun intToDp(dp: Int): Int {
19 | return ceil((dp * Resources.getSystem().displayMetrics.density).toDouble()).toInt()
20 | }
21 |
22 | fun d(view: View): Rect {
23 | val iArr = IntArray(2)
24 | view.getLocationOnScreen(iArr)
25 | return Rect(iArr[0], iArr[1], iArr[0] + view.measuredWidth, iArr[1] + view.measuredHeight)
26 | }
27 |
28 | @SuppressLint("InflateParams")
29 | fun a(list: List, setListViewParams: ((Pair) -> Unit)? = null, onClick: (PopupItem) -> Unit) {
30 | if (!a()) {
31 | val context = this.d.context
32 | val inflate = LayoutInflater.from(context).inflate(R.layout.replica_popup, null, false)
33 | val dialogActionsListView = inflate.findViewById(R.id.dialog_actions_list_content)
34 | setListViewParams?.invoke(Pair(inflate.findViewById(R.id.dialog_actions_list_container), dialogActionsListView))
35 | dialogActionsListView.setActions(list)
36 | dialogActionsListView.setActionClickListener(onClick)
37 |
38 | inflate.measure(View.MeasureSpec.makeMeasureSpec(this.d.rootView.measuredWidth, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(this.d.rootView.measuredHeight - intToDp(64), View.MeasureSpec.AT_MOST))
39 | inflate.layout(0, 0, inflate.measuredWidth, inflate.measuredHeight)
40 |
41 | val d2 = d(this.d)
42 | val measuredWidth = (d2.right - inflate.measuredWidth) + intToDp(8)
43 | val b2 = d2.top - intToDp(8)
44 | val rect = Rect(measuredWidth, b2, inflate.measuredWidth + measuredWidth, inflate.measuredHeight + b2)
45 |
46 | this.c = PopupWindowImpl(context).apply {
47 | contentView = inflate
48 | width = rect.width()
49 | height = rect.height()
50 | setOnDismissListener { c = null }
51 | showAtLocation(d, 0, rect.left, rect.top)
52 | }
53 | }
54 | }
55 |
56 | fun dismiss() {
57 | if (a()) {
58 | b?.invoke()
59 | c?.dismiss()
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/DividerStyle.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import androidx.annotation.UiThread
4 |
5 | @UiThread
6 | data class DividerStyle(
7 | var dividerHeight: Int,
8 | var dividerSize: Int,
9 | var dividerColor: Int
10 | )
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/PopupContentAnimator.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.animation.*
4 | import android.content.res.Resources
5 | import android.graphics.Rect
6 | import android.os.Handler
7 | import android.os.Looper
8 | import android.view.View
9 | import androidx.annotation.UiThread
10 | import androidx.core.os.postDelayed
11 | import androidx.interpolator.view.animation.FastOutLinearInInterpolator
12 | import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
13 | import kotlin.math.ceil
14 |
15 | @UiThread
16 | class PopupContentAnimator(private val g: View) {
17 | companion object {
18 | private fun intToDp(dp: Int): Int {
19 | return ceil((dp * Resources.getSystem().displayMetrics.density).toDouble()).toInt()
20 | }
21 |
22 | val h = (-(intToDp(4))).toFloat()
23 | val j = (-(intToDp(4))).toFloat()
24 |
25 | val i = LinearOutSlowInInterpolator()
26 | val k = FastOutLinearInInterpolator()
27 | }
28 |
29 | var b: Animator? = null
30 | var c: Animator? = null
31 | private val d = Handler(Looper.getMainLooper())
32 | private var e: (() -> Unit)? = null
33 | private var f: (() -> Unit)? = null
34 |
35 | fun a(action: () -> Unit) {
36 | this.f = action
37 | }
38 |
39 | private fun b() {
40 | val rect = Rect(0, 0, this.g.measuredWidth, 0)
41 | val rect2 = Rect(0, 0, this.g.measuredWidth, this.g.measuredHeight)
42 | this.g.apply {
43 | clipBounds = rect
44 | alpha = 0.0f
45 | translationY = h
46 | visibility = View.VISIBLE
47 | }
48 |
49 | val ofObject = ObjectAnimator.ofObject(this.g, "clipBounds", RectEvaluator(), rect, rect2)
50 | val ofFloat = ObjectAnimator.ofFloat(this.g, View.ALPHA, 0.0f, 1.0f)
51 | val ofFloat2 = ObjectAnimator.ofFloat(this.g, View.TRANSLATION_Y, h, 0.0f)
52 | this.b = AnimatorSet().apply {
53 | addListener(object: AnimatorListenerAdapter() {
54 | override fun onAnimationEnd(animation: Animator?) {
55 | b = null
56 | c = null
57 | g.visibility = View.VISIBLE
58 | }
59 | })
60 | addListener(object: AnimatorListenerAdapter() {
61 | override fun onAnimationEnd(animation: Animator?) {
62 | b = null
63 | c = null
64 | e?.invoke()
65 | }
66 | })
67 | duration = 225
68 | interpolator = i
69 | playTogether(ofObject, ofFloat, ofFloat2)
70 | start()
71 | }
72 | }
73 |
74 | fun a(z: Boolean) {
75 | if (!a()) {
76 | e()
77 | if (d()) {
78 | b()
79 | } else {
80 | b { b() }
81 | }
82 | }
83 | }
84 |
85 | fun b(z: Boolean) {
86 | if (a()) {
87 | if (z) {
88 | e()
89 | if (d()) {
90 | c()
91 | } else {
92 | b { c() }
93 | }
94 | } else {
95 | e()
96 | this.g.visibility = View.INVISIBLE
97 | this.f?.invoke()
98 | }
99 | }
100 | }
101 |
102 | private fun c() {
103 | this.g.apply {
104 | clipBounds = null
105 | alpha = 1.0f
106 | translationY = 0.0f
107 | visibility = View.VISIBLE
108 | }
109 | val ofFloat = ObjectAnimator.ofFloat(this.g, View.ALPHA, 1.0f, 0.0f)
110 | val ofFloat2 = ObjectAnimator.ofFloat(this.g, View.TRANSLATION_Y, 0.0f, j)
111 | this.c = AnimatorSet().apply {
112 | addListener(object: AnimatorListenerAdapter() {
113 | override fun onAnimationEnd(animation: Animator?) {
114 | b = null
115 | c = null
116 | g.visibility = View.INVISIBLE
117 | }
118 | })
119 | addListener(object: AnimatorListenerAdapter() {
120 | override fun onAnimationEnd(animation: Animator?) {
121 | b = null
122 | c = null
123 | f?.invoke()
124 | }
125 | })
126 | duration = 150
127 | interpolator = k
128 | playTogether(ofFloat, ofFloat2)
129 | start()
130 | }
131 | }
132 |
133 | private fun d(): Boolean {
134 | return this.g.measuredHeight > 0
135 | }
136 |
137 | private fun b(aVar: () -> Unit) {
138 | this.g.visibility = View.INVISIBLE
139 | this.d.postDelayed(50) {
140 | aVar.invoke()
141 | }
142 | }
143 |
144 | private fun e() {
145 | this.b?.cancel()
146 | this.b = null
147 | this.c?.cancel()
148 | this.c = null
149 | this.d.removeCallbacksAndMessages(null)
150 | }
151 |
152 | private fun a(): Boolean {
153 | if (this.b == null) {
154 | if (this.g.visibility == View.VISIBLE) {
155 | if (this.c == null) {
156 | return true
157 | }
158 | }
159 | return false
160 | }
161 | return true
162 | }
163 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/PopupItem.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import androidx.annotation.DrawableRes
4 | import androidx.annotation.StringRes
5 |
6 | data class PopupItem(
7 | @DrawableRes val icon: Int,
8 | @StringRes val title: Int,
9 | val group: Int,
10 | val id: String
11 | )
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/PopupWindowImpl.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.content.Context
4 | import android.graphics.Canvas
5 | import android.graphics.ColorFilter
6 | import android.graphics.PixelFormat
7 | import android.graphics.drawable.Drawable
8 | import android.os.Handler
9 | import android.view.View
10 | import android.widget.PopupWindow
11 | import androidx.annotation.UiThread
12 |
13 | @UiThread
14 | class PopupWindowImpl(context: Context): PopupWindow(context) {
15 | private val f1304a = Handler()
16 | private var b: PopupContentAnimator? = null
17 |
18 | init {
19 | isClippingEnabled = false
20 | isFocusable = true
21 | animationStyle = 0
22 | setBackgroundDrawable(object: Drawable() {
23 | override fun draw(canvas: Canvas) {
24 |
25 | }
26 |
27 | override fun setAlpha(alpha: Int) {
28 |
29 | }
30 |
31 | override fun getOpacity(): Int {
32 | return PixelFormat.TRANSPARENT
33 | }
34 |
35 | override fun setColorFilter(colorFilter: ColorFilter?) {
36 |
37 | }
38 |
39 | })
40 | }
41 |
42 | override fun showAsDropDown(view: View?) {
43 | run {
44 | super.showAsDropDown(view)
45 | }
46 | }
47 |
48 | override fun showAsDropDown(view: View?, i: Int, i2: Int) {
49 | run {
50 | super.showAsDropDown(view, i, i2)
51 | }
52 | }
53 |
54 | override fun showAsDropDown(view: View?, i: Int, i2: Int, i3: Int) {
55 | run {
56 | super.showAsDropDown(view, i, i2, i3)
57 | }
58 | }
59 |
60 | override fun showAtLocation(view: View?, i: Int, i2: Int, i3: Int) {
61 | run {
62 | super.showAtLocation(view, i, i2, i3)
63 | }
64 | }
65 |
66 | private fun run(aVar: () -> Unit) {
67 | this.b = PopupContentAnimator(contentView)
68 | this.b?.b(false)
69 | aVar.invoke()
70 | this.f1304a.post {
71 | this.b?.a(true)
72 | }
73 | }
74 |
75 | override fun dismiss() {
76 | this.f1304a.removeCallbacksAndMessages(null)
77 | this.b?.a {
78 | b = null
79 | super.dismiss()
80 | }
81 | this.b?.b(true)
82 | }
83 | }
--------------------------------------------------------------------------------
/app/src/main/java/ua/itaysonlab/replica/vkpopup/VkLibActionsListView.kt:
--------------------------------------------------------------------------------
1 | package ua.itaysonlab.replica.vkpopup
2 |
3 | import android.content.Context
4 | import android.content.res.Resources
5 | import android.graphics.drawable.Drawable
6 | import android.util.AttributeSet
7 | import android.util.DisplayMetrics
8 | import androidx.annotation.ColorInt
9 | import androidx.annotation.DrawableRes
10 | import androidx.annotation.Px
11 | import androidx.annotation.UiThread
12 | import androidx.core.content.ContextCompat
13 | import androidx.recyclerview.widget.LinearLayoutManager
14 | import androidx.recyclerview.widget.RecyclerView
15 | import ua.itaysonlab.homefeeder.R
16 | import kotlin.math.ceil
17 |
18 | @UiThread
19 | open class VkLibActionsListView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0): RecyclerView(context, attrs, defStyleAttr) {
20 | private val f2979a: DividerStyle
21 | private val b: ActionStyle
22 | private var c: ActionDivider
23 | private var d: ActionAdapter
24 |
25 | init {
26 | val attr = context.obtainStyledAttributes(attrs, R.styleable.VkLibActionsListView, defStyleAttr, 0)
27 | val dHeight = attr.getDimensionPixelSize(R.styleable.VkLibActionsListView_vklib_alv_dividerHeight, a(1))
28 | val dSize = attr.getDimensionPixelSize(R.styleable.VkLibActionsListView_vklib_alv_dividerSize, a(1))
29 | val dColor = attr.getColor(R.styleable.VkLibActionsListView_vklib_alv_dividerColor, -16777216)
30 | this.f2979a = DividerStyle(dHeight, dSize, dColor)
31 |
32 | val oBg = attr.getDrawable(R.styleable.VkLibActionsListView_vklib_alv_optionBackground)
33 | val paddingStart = attr.getDimensionPixelSize(R.styleable.VkLibActionsListView_vklib_alv_optionPaddingStart, 0)
34 | val paddingEnd = attr.getDimensionPixelSize(R.styleable.VkLibActionsListView_vklib_alv_optionPaddingEnd, 0)
35 | val iconSpace = attr.getDimensionPixelSize(R.styleable.VkLibActionsListView_vklib_alv_optionIconLabelSpace, 0)
36 | val iconTint = Integer.valueOf(attr.getColor(R.styleable.VkLibActionsListView_vklib_alv_optionIconTint, -16777216))
37 | val textSize = attr.getDimensionPixelSize(R.styleable.VkLibActionsListView_vklib_alv_optionLabelTextSize, (((getDisplayMetrics().scaledDensity * 16.0f) + 0.5f).toInt()))
38 | val textColor = attr.getColor(R.styleable.VkLibActionsListView_vklib_alv_optionLabelTextColor, -16777216)
39 | this.b = ActionStyle(oBg, paddingStart, paddingEnd, iconSpace, iconTint, textSize, textColor)
40 | attr.recycle()
41 |
42 | this.c = ActionDivider(this.f2979a)
43 | this.d = ActionAdapter(context, this.b)
44 | this.layoutManager = LinearLayoutManager(context, VERTICAL, false)
45 | this.addItemDecoration(this.c)
46 | this.adapter = this.d
47 | }
48 |
49 | fun setDividerHeight(@Px i: Int) {
50 | this.f2979a.dividerHeight = i
51 | a()
52 | }
53 |
54 | fun setDividerSize(@Px i: Int) {
55 | this.f2979a.dividerSize = i
56 | a()
57 | }
58 |
59 | fun setDividerColor(@ColorInt i: Int) {
60 | this.f2979a.dividerColor = i
61 | a()
62 | }
63 |
64 | fun setActionBackground(@DrawableRes i: Int) {
65 | if (i != 0) {
66 | setActionBackground(ContextCompat.getDrawable(context, i))
67 | } else {
68 | setActionBackground(null)
69 | }
70 | }
71 |
72 | fun setActionBackground(drawable: Drawable?) {
73 | this.b.optionBackground = drawable
74 | b()
75 | }
76 |
77 | fun setActionPaddingStart(@Px i: Int) {
78 | this.b.paddingStart = i
79 | b()
80 | }
81 |
82 | fun setActionIconTint(@ColorInt i: Int) {
83 | this.b.iconTint = i
84 | b()
85 | }
86 |
87 | fun setActionPaddingEnd(@Px i: Int) {
88 | this.b.paddingEnd = i
89 | b()
90 | }
91 |
92 | fun setActionIconLabelSpace(@Px i: Int) {
93 | this.b.iconSpace = i
94 | b()
95 | }
96 |
97 | fun setActionLabelTextSize(@Px i: Int) {
98 | this.b.textSize = i
99 | b()
100 | }
101 |
102 | fun setActionLabelTextColor(@ColorInt i: Int) {
103 | this.b.textColor = i
104 | b()
105 | }
106 |
107 | fun setActionClickListener(cVar: (PopupItem) -> Unit) {
108 | this.d.a(cVar)
109 | }
110 |
111 | fun setActions(list: List) {
112 | this.d.a(list)
113 | if (list.isNotEmpty()) layoutManager?.scrollToPosition(0)
114 | }
115 |
116 | private fun a() {
117 | this.c = ActionDivider(this.f2979a)
118 | adapter?.notifyDataSetChanged()
119 | }
120 |
121 | private fun b() {
122 | this.d = ActionAdapter(context, this.b)
123 | adapter = this.d
124 | }
125 |
126 | private fun getDisplayMetrics(): DisplayMetrics {
127 | return Resources.getSystem().displayMetrics
128 | }
129 |
130 | private fun a(i: Int): Int {
131 | return ceil((getDisplayMetrics().density * 1.0f)).toInt()
132 | }
133 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/vkim_bg_overlay.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/drawable-hdpi/vkim_bg_overlay.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/vkim_bg_overlay.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/drawable-mdpi/vkim_bg_overlay.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
9 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
38 |
44 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/vkim_bg_overlay.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/drawable-xhdpi/vkim_bg_overlay.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/vkim_bg_overlay.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/drawable-xxhdpi/vkim_bg_overlay.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/vkim_bg_overlay.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/drawable-xxxhdpi/vkim_bg_overlay.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_info_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_info_outline_28.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
6 |
8 |
14 |
22 |
30 |
38 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more_vertical_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_replay_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_report_outline_28.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_services_outline_28.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_outline_28.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/remove_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/v2_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
29 |
30 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_card_action.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_card_story_large.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
28 |
29 |
39 |
40 |
53 |
54 |
62 |
63 |
70 |
71 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_card_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
18 |
19 |
26 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/notification_generic_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
14 |
15 |
19 |
26 |
27 |
34 |
35 |
45 |
46 |
47 |
57 |
58 |
59 |
69 |
70 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/notification_simple.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/overlay_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
22 |
23 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/overlay_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
22 |
23 |
27 |
28 |
33 |
34 |
35 |
36 |
42 |
43 |
50 |
51 |
56 |
57 |
65 |
66 |
73 |
74 |
80 |
81 |
82 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/plugin_manager_empty.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
14 |
24 |
25 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/plugin_manager_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
29 |
30 |
34 |
35 |
41 |
42 |
48 |
49 |
56 |
57 |
62 |
63 |
64 |
72 |
73 |
78 |
79 |
80 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/plugin_manager_ui.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
17 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preview.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/replica_popup.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vklib_actionslistview_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/bottom_nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/navigation/mobile_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/bools.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4285f4
4 | #80000000
5 | #121212
6 | #212121
7 | #ffffff
8 | #a0a0a0
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Автоматически (из лаунчера)
5 | - Автоматически (из системы)
6 | - Светлая
7 | - Темная
8 |
9 |
10 |
11 | - Непрозрачный
12 | - 75\uff05
13 | - 50\uff05
14 | - 25\uff05
15 | - Прозрачный
16 |
17 |
18 |
19 | - Из темы
20 | - Светлый
21 | - Темный
22 | - AMOLED
23 | - Из лаунчера: Основной цвет
24 | - Из лаунчера: Вторичный цвет
25 | - Из лаунчера: Третичный цвет
26 |
27 |
28 |
29 | - час назад
30 | - два часа назад
31 | - три часа назад
32 |
33 |
34 |
35 | - Январь
36 | - Февраль
37 | - Март
38 | - Апрель
39 | - Май
40 | - Июнь
41 | - Июль
42 | - Август
43 | - Сентябрь
44 | - Октябрь
45 | - Ноябрь
46 | - Декабрь
47 |
48 |
49 |
50 | - Янв
51 | - Фев
52 | - Мар
53 | - Апр
54 | - Мая
55 | - Июн
56 | - Июл
57 | - Авг
58 | - Сен
59 | - Окт
60 | - Ноя
61 | - Дек
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/plurals.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - %,d минут назад
5 | - %,d минуту назад
6 | - %,d минуты назад
7 |
8 |
9 | - %,d секунд назад
10 | - %,d секунду назад
11 | - %,d секунды назад
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Настройки
3 | О приложении
4 | Источники данных
5 |
6 | сейчас
7 | в
8 | @string/date_at
9 | сегодня
10 | завтра
11 | вчера
12 |
13 | Контакты
14 | Официальный канал в Telegram
15 | Разработчик
16 | Исходный код
17 |
18 | Внешний вид
19 | Прозрачность фона
20 | Тема
21 | Компактные элементы списка
22 |
23 | Фон карточек
24 | Фон ленты
25 |
26 | Категория ленты \"Уведомления\"
27 | Доступ к уведомлениям
28 | Есть
29 | Нету, нажмите сюда для подробной информации
30 | HomeFeeder нужно разрешение \"Доступ к уведомлениям\" для показа уведомлений в ленте. Данные обрабатываются на устройстве и только на нем.\n\nВозможно, некоторые функции HomeFeeder могут быть недоступными до выдачи разрешения.
31 | Настройки
32 | Отменить
33 |
34 | Доступ к памяти
35 | HomeFeeder нужно разрешение \"Память\" для точного предпросмотра и сохранения данных.\n\nДанное разрешение необязательно, но рекомендуется для нормального использования.
36 | Запросить
37 |
38 | Разрешение не выдано
39 | Нажмите для перезагрузки
40 | HomeFeeder нужно разрешение \"Доступ к уведомлениям\" для показа уведомлений в ленте.
41 | Проверьте что вы выдали разрешение \"Доступ к уведомлениям\"
42 |
43 | Уведомления
44 | Погода
45 |
46 | Использовать системные цвета обоев
47 | вместо опций \"Из лаунчера:\"
48 | Требуется Android 8.1 или новее
49 |
50 | Перезагрузить
51 |
52 | Источники не обнаружены
53 | HomeFeeder использует их для получения данных
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v27/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Automatically (from launcher)
5 | - Automatically (from system)
6 | - Light
7 | - Dark
8 |
9 |
10 |
11 | - Non-transparent
12 | - 75\uff05
13 | - 50\uff05
14 | - 25\uff05
15 | - Transparent
16 |
17 |
18 |
19 | - non_transparent
20 | - more_half
21 | - half
22 | - less_half
23 | - transparent
24 |
25 |
26 |
27 | - Theme-based
28 | - White
29 | - Dark
30 | - AMOLED
31 | - Launcher: Primary color
32 | - Launcher: Secondary color
33 | - Launcher: Tertiary color
34 |
35 |
36 |
37 | - theme
38 | - white
39 | - dark
40 | - amoled
41 | - launcher_primary
42 | - launcher_secondary
43 | - launcher_tertiary
44 |
45 |
46 |
47 | - auto_launcher
48 | - auto_system
49 | - light
50 | - dark
51 |
52 |
53 |
54 | - an hour ago
55 | - two hours ago
56 | - three hours ago
57 |
58 |
59 |
60 | - January
61 | - February
62 | - March
63 | - April
64 | - May
65 | - June
66 | - July
67 | - August
68 | - September
69 | - October
70 | - November
71 | - December
72 |
73 |
74 |
75 | - Jan
76 | - Feb
77 | - Mar
78 | - Apr
79 | - May
80 | - Jun
81 | - Jul
82 | - Aug
83 | - Sep
84 | - Oct
85 | - Nov
86 | - Dec
87 |
88 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/bools.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4285f4
4 |
5 | #A0FFFFFF
6 | #ffffff
7 |
8 | #ffffff
9 | #121212
10 | #f0f0f0
11 |
12 | #000000
13 | #707070
14 |
15 | #f0f0f0
16 | #212121
17 | #000000
18 | #ffffff
19 | #a0000000
20 | #a0FFFFFF
21 |
22 | #ff453a
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 14dp
5 |
6 | 16dp
7 | 16dp
8 |
9 | 4dp
10 | 8dp
11 | 140dp
12 |
13 | 12dp
14 | 12dp
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/plurals.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - %,d minutes ago
5 | - %,d minute ago
6 | - %,d minutes ago
7 |
8 |
9 | - %,d seconds ago
10 | - %,d second ago
11 | - %,d seconds ago
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HomeFeeder
3 |
4 | Settings
5 | About
6 | Data sources
7 |
8 | %1$d %2$s
9 | %1$d %2$s %3$d
10 | now
11 | at
12 | @string/date_at
13 | today
14 | tomorrow
15 | yesterday
16 |
17 | Contacts
18 | Official Telegram channel
19 | Developer
20 | Source code
21 |
22 | Appearance
23 | Overlay background transparency
24 | Overlay theme
25 | Compact item layout
26 |
27 | Card background
28 | Overlay background
29 |
30 | Notification feed category
31 | Notification permission
32 | Granted
33 | Not granted, click here to allow
34 | HomeFeeder needs \"Notification access\" permission to show your notifications in a overlay. Data is processed only on-device and won\'t be sent from it.\n\nPlease note that some features of HomeFeeder might be unavailable until you grant the permission.
35 | Open settings
36 | Cancel
37 |
38 | Storage permission
39 | HomeFeeder needs \"Read external storage\" permission to save various data and show accurate previews.\n\nThis permission is not needed, but recommended for using.
40 | Request
41 |
42 | No permission granted
43 | Click here to reload
44 | HomeFeeder needs \"Notification access\" permission to show your notifications in a overlay.
45 | Please verify you have allowed \"Notification access\" permission and try again.
46 |
47 | Notifications
48 | Weather
49 |
50 | Use system wallpaper colors
51 | instead of \"Launcher:\" options
52 | Requires Android 8.1 or newer
53 |
54 | Reload
55 |
56 | No sources installed
57 | HomeFeeder uses them to display data
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
17 |
18 |
21 |
22 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/pref_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
11 |
14 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/pref_general.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
14 |
20 |
24 |
29 |
35 |
41 |
42 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.6.10'
5 |
6 | repositories {
7 | google()
8 | mavenCentral()
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:7.1.1'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | mavenCentral()
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTaysonLab/HomeFeeder/ec36735b596a0af3f3c0cf79f03d9ab42b7d1e14/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jul 10 12:40:05 EEST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':homefeeder-sdk', ':homefeeder-rss'
2 | rootProject.name='HomeFeeder'
3 |
--------------------------------------------------------------------------------