├── settings.gradle
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── microg-ui-tools
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable-v21
│ │ │ └── switchbar_background.xml
│ │ ├── drawable
│ │ │ ├── empty.xml
│ │ │ ├── switchbar_background.xml
│ │ │ ├── self_check.xml
│ │ │ ├── ic_expand_less.xml
│ │ │ └── ic_expand_more.xml
│ │ ├── values-eo
│ │ │ └── strings.xml
│ │ ├── values-es
│ │ │ └── strings.xml
│ │ ├── values-ro
│ │ │ └── strings.xml
│ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── themes.xml
│ │ │ └── strings.xml
│ │ ├── layout
│ │ │ ├── preference_widget_radiobutton.xml
│ │ │ ├── toolbar.xml
│ │ │ ├── self_check.xml
│ │ │ ├── dashboard_activity.xml
│ │ │ ├── settings_activity.xml
│ │ │ ├── self_check_group.xml
│ │ │ ├── switch_bar.xml
│ │ │ ├── app_bar.xml
│ │ │ ├── self_check_entry.xml
│ │ │ ├── about_root.xml
│ │ │ └── condition_card.xml
│ │ ├── values-v14
│ │ │ └── themes.xml
│ │ ├── layout-v14
│ │ │ └── preference_category_dashboard.xml
│ │ ├── values-sr
│ │ │ └── strings.xml
│ │ ├── values-pl
│ │ │ └── strings.xml
│ │ ├── values-zh-rTW
│ │ │ └── strings.xml
│ │ ├── values-fr
│ │ │ └── strings.xml
│ │ ├── values-uk
│ │ │ └── strings.xml
│ │ ├── values-de
│ │ │ └── strings.xml
│ │ ├── values-ru
│ │ │ └── strings.xml
│ │ └── layout-v21
│ │ │ └── preference_material.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── org
│ │ └── microg
│ │ └── tools
│ │ ├── selfcheck
│ │ ├── SelfCheckGroup.java
│ │ └── PermissionCheckGroup.java
│ │ └── ui
│ │ ├── ResourceSettingsFragment.java
│ │ ├── TintIconPreference.java
│ │ ├── AbstractSettingsFragment.java
│ │ ├── RadioButtonPreference.java
│ │ ├── LongTextPreference.java
│ │ ├── ToggleSwitch.java
│ │ ├── SwitchBarResourceSettingsFragment.java
│ │ ├── AbstractSettingsActivity.java
│ │ ├── DimmableIconPreference.java
│ │ ├── AbstractDashboardActivity.java
│ │ ├── DialogPreference.java
│ │ ├── AbstractSelfCheckFragment.java
│ │ ├── AbstractAboutFragment.java
│ │ ├── SwitchBar.java
│ │ └── Condition.java
└── build.gradle
├── README.md
├── .travis.yml
├── Android.mk
├── gradlew
└── LICENSE
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':microg-ui-tools'
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | .gradle/
3 | local.properties
4 | *.iml
5 | .idea/
6 | BuildConfig.java
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microg/android_external_MicroGUiTools/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Feb 7 18:49:43 UTC 2017
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-4.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/drawable-v21/switchbar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
UI Tools
2 | ======
3 | [](https://travis-ci.org/microg/android_external_MicroGUiTools)
4 | This repository holds a library providing various UI features used in microG apps (GmsCore and UnifiedNlp).
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | sudo: false
3 | before_script:
4 | - echo sdk.dir $ANDROID_HOME > local.properties
5 | script:
6 | - jdk_switcher use oraclejdk8
7 | - export TERM=dumb
8 | - export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m"
9 | - ./gradlew build
10 | android:
11 | components:
12 | - tools
13 | - platform-tools
14 | - build-tools-27.0.3
15 | - android-27
16 | - extra-android-m2repository
17 | licenses:
18 | - '.+'
19 | before_install:
20 | - yes | sdkmanager "platforms;android-27"
21 | before_cache:
22 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
23 | cache:
24 | directories:
25 | - $HOME/.gradle/caches/
26 | - $HOME/.gradle/wrapper/
27 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/drawable/empty.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-eo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/drawable/switchbar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
20 |
21 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | #ff263238
19 | #ff21272b
20 | #ff009688
21 |
22 | #ff37474f
23 | #ff7fcac3
24 |
25 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/preference_widget_radiobutton.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-v14/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
13 |
14 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/toolbar.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
25 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/drawable/self_check.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
27 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/self_check.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
23 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout-v14/preference_category_dashboard.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
12 |
13 |
24 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/drawable/ic_expand_less.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
25 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/drawable/ic_expand_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
25 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-sr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | Поставка
20 |
21 | микроГ самопровера
22 | Провера исправности подешавања система за коришћење микроГ услуга.
23 |
24 | Дозволе одобрене
25 | Дозволе за %1$s:
26 | Тапните овде да одобрите дозволе за %1$s. Не одобравање дозвола може да резултира чудним понашањем апликација.
27 |
28 |
29 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/selfcheck/SelfCheckGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.selfcheck;
18 |
19 | import android.content.Context;
20 | import android.support.v4.app.Fragment;
21 |
22 | public interface SelfCheckGroup {
23 | String getGroupName(Context context);
24 |
25 | void doChecks(Context context, ResultCollector collector);
26 |
27 | interface ResultCollector {
28 | void addResult(String name, Result value, String resolution);
29 |
30 | void addResult(String name, Result value, String resolution, CheckResolver resolver);
31 | }
32 |
33 | interface CheckResolver {
34 | void tryResolve(Fragment fragment);
35 | }
36 |
37 | enum Result {
38 | Positive, Negative, Unknown
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/ResourceSettingsFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.os.Bundle;
20 | import android.support.annotation.Nullable;
21 |
22 | public class ResourceSettingsFragment extends AbstractSettingsFragment {
23 |
24 | public static final String EXTRA_PREFERENCE_RESOURCE = "preferencesResource";
25 |
26 | protected int preferencesResource;
27 |
28 | @Override
29 | public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
30 | Bundle b = getArguments();
31 | if (b != null) {
32 | preferencesResource = b.getInt(EXTRA_PREFERENCE_RESOURCE, preferencesResource);
33 | }
34 | if (preferencesResource != 0) {
35 | addPreferencesFromResource(preferencesResource);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/dashboard_activity.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
21 |
22 |
23 |
24 |
29 |
30 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/TintIconPreference.java:
--------------------------------------------------------------------------------
1 | package org.microg.tools.ui;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.support.v4.graphics.drawable.DrawableCompat;
6 | import android.support.v7.preference.PreferenceViewHolder;
7 | import android.util.AttributeSet;
8 | import android.util.TypedValue;
9 |
10 | import static android.os.Build.VERSION.SDK_INT;
11 | import static android.os.Build.VERSION_CODES.LOLLIPOP;
12 |
13 | public class TintIconPreference extends DimmableIconPreference {
14 |
15 | public TintIconPreference(Context context) {
16 | this(context, (AttributeSet) null);
17 | }
18 |
19 | public TintIconPreference(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 | }
22 |
23 | private static int getThemeAccentColor(Context context) {
24 | int colorAttr;
25 | if (SDK_INT >= LOLLIPOP) {
26 | colorAttr = android.R.attr.colorAccent;
27 | } else {
28 | //Get colorAccent defined for AppCompat
29 | colorAttr = context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName());
30 | }
31 | TypedValue outValue = new TypedValue();
32 | context.getTheme().resolveAttribute(colorAttr, outValue, true);
33 | return outValue.data;
34 | }
35 |
36 | @Override
37 | public void onBindViewHolder(PreferenceViewHolder view) {
38 | super.onBindViewHolder(view);
39 | Drawable icon = getIcon();
40 | if (icon != null) {
41 | DrawableCompat.setTint(icon, getThemeAccentColor(getContext()));
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 | include $(CLEAR_VARS)
3 |
4 | # Generate Gradle BuildConfig.mk file since AOSP does not handle that
5 | # Remove the generated file if you want it to be regenerated with new values
6 |
7 | UITOOLS_BUILDCONFIG_CLASS := microg-ui-tools/src/main/java/org/microg/tools/ui/BuildConfig.java
8 | UITOOLS_BC_PATH := $(LOCAL_PATH)/$(UITOOLS_BUILDCONFIG_CLASS)
9 | UITOOLS_BC_APPLICATION_ID := "org.microg.tools.ui"
10 | UITOOLS_BC_VERSION_CODE := -1
11 |
12 | $(UITOOLS_BC_PATH):
13 | echo "/**" > $(UITOOLS_BC_PATH)
14 | echo "* Automatically generated file. DO NOT MODIFY" >> $(UITOOLS_BC_PATH)
15 | echo "*/" >> $(UITOOLS_BC_PATH)
16 | echo "package "$(UITOOLS_BC_APPLICATION_ID)";" >> $(UITOOLS_BC_PATH)
17 | echo "public final class BuildConfig {" >> $(UITOOLS_BC_PATH)
18 | echo " public static final String APPLICATION_ID = \""$(UITOOLS_BC_APPLICATION_ID)"\";" >> $(UITOOLS_BC_PATH)
19 | echo " public static final int VERSION_CODE = "$(UITOOLS_BC_VERSION_CODE)";" >> $(UITOOLS_BC_PATH)
20 | echo " private BuildConfig() {}" >> $(UITOOLS_BC_PATH)
21 | echo "}" >> $(UITOOLS_BC_PATH)
22 |
23 | LOCAL_MODULE := MicroGUiTools
24 | LOCAL_SRC_FILES := $(call all-java-files-under, microg-ui-tools/src/main/java)
25 | LOCAL_SRC_FILES += $(UITOOLS_BUILDCONFIG_CLASS)
26 |
27 | LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/microg-ui-tools/src/main/res
28 | LOCAL_RESOURCE_DIR += frameworks/support/v7/appcompat/res
29 | LOCAL_MANIFEST_FILE := microg-ui-tools/src/main/AndroidManifest.xml
30 | LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-appcompat
31 |
32 | LOCAL_AAPT_FLAGS := --auto-add-overlay
33 | LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat
34 |
35 | include $(BUILD_STATIC_JAVA_LIBRARY)
36 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
21 |
22 |
23 |
24 |
30 |
31 |
35 |
36 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/self_check_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
23 |
33 |
34 |
39 |
40 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/AbstractSettingsFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.support.v4.app.DialogFragment;
20 | import android.support.v7.preference.Preference;
21 |
22 | import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat;
23 |
24 | public abstract class AbstractSettingsFragment extends PreferenceFragmentCompat {
25 | private static final String TAG = AbstractSettingsFragment.class.getSimpleName();
26 |
27 | private static final String DIALOG_FRAGMENT_TAG =
28 | "android.support.v7.preference.PreferenceFragment.DIALOG";
29 |
30 | @Override
31 | public void onDisplayPreferenceDialog(Preference preference) {
32 | if (preference instanceof DialogPreference) {
33 | DialogFragment f = DialogPreference.DialogPreferenceCompatDialogFragment.newInstance(preference.getKey());
34 | f.setTargetFragment(this, 0);
35 | f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
36 | } else {
37 | super.onDisplayPreferenceDialog(preference);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
27 |
28 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/switch_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
33 |
34 |
43 |
44 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/RadioButtonPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.annotation.SuppressLint;
20 | import android.content.Context;
21 | import android.support.v4.content.res.TypedArrayUtils;
22 | import android.support.v7.preference.CheckBoxPreference;
23 | import android.util.AttributeSet;
24 |
25 | public class RadioButtonPreference extends CheckBoxPreference {
26 |
27 | public RadioButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
28 | this(context, attrs, defStyleAttr, 0);
29 | }
30 |
31 | public RadioButtonPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
32 | super(context, attrs, defStyleAttr, defStyleRes);
33 | setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
34 | }
35 |
36 | @SuppressLint("RestrictedApi")
37 | public RadioButtonPreference(Context context, AttributeSet attrs) {
38 | this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.checkBoxPreferenceStyle,
39 | android.R.attr.checkBoxPreferenceStyle));
40 | }
41 |
42 | public RadioButtonPreference(Context context) {
43 | this(context, null);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/LongTextPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.content.Context;
20 | import android.support.v7.preference.Preference;
21 | import android.support.v7.preference.PreferenceViewHolder;
22 | import android.util.AttributeSet;
23 | import android.widget.TextView;
24 |
25 | public class LongTextPreference extends Preference {
26 |
27 | public LongTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
28 | super(context, attrs, defStyleAttr, defStyleRes);
29 | }
30 |
31 | public LongTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
32 | super(context, attrs, defStyleAttr);
33 | }
34 |
35 | public LongTextPreference(Context context, AttributeSet attrs) {
36 | super(context, attrs);
37 | }
38 |
39 | public LongTextPreference(Context context) {
40 | super(context);
41 | }
42 |
43 | @Override
44 | public void onBindViewHolder(PreferenceViewHolder holder) {
45 | super.onBindViewHolder(holder);
46 | TextView view = (TextView) holder.findViewById(android.R.id.summary);
47 | if (view != null) {
48 | view.setMaxLines(Integer.MAX_VALUE);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/microg-ui-tools/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2016 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'com.android.library'
18 |
19 | String getMyVersionName() {
20 | def stdout = new ByteArrayOutputStream()
21 | if (rootProject.file("gradlew").exists())
22 | exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout }
23 | else // automatic build system, don't tag dirty
24 | exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout }
25 | return stdout.toString().trim().substring(1)
26 | }
27 |
28 | android {
29 | compileSdkVersion androidCompileSdk()
30 | buildToolsVersion "$androidBuildVersionTools"
31 |
32 | defaultConfig {
33 | versionName getMyVersionName()
34 | minSdkVersion androidMinSdk()
35 | targetSdkVersion androidTargetSdk()
36 | }
37 |
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_8
40 | targetCompatibility JavaVersion.VERSION_1_8
41 | }
42 |
43 | lintOptions {
44 | // TODO: Remove MissingTranslation once we have stable strings and proper translations.
45 | disable 'MissingTranslation'
46 | }
47 | }
48 |
49 | dependencies {
50 | implementation "com.android.support:support-v4:$supportLibraryVersion"
51 | implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
52 | implementation "com.takisoft.fix:preference-v7:$supportLibraryVersion.0"
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-pl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | Narzędzia UI microG
20 | Licencja Apache 2.0, Zespół microG
21 |
22 | Wersja %1$s
23 | %1$s %2$s
24 | Wszelkie prawa zastrzeżone.
25 |
26 | Ustawienia
27 |
28 | Samo-sprawdzenie
29 | Sprawdza, czy system jest poprawnie skonfigurowany do korzystania z microG.
30 |
31 | Udzielono uprawnień
32 | Uprawnienie do %1$s:
33 | Stuknij, aby udzielić uprawnienia na %1$s. Nieudzielenie uprawnienia może powodować problemy z aplikacjami.
34 |
35 | Demo microG UI
36 | Podsumowanie
37 | Wersja v0.1.0
38 | Użyte biblioteki
39 |
40 | Licencja Apache 2.0, The Android Open Source Project
41 |
42 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | microG UI Tools
20 | Apache License 2.0, microG團隊
21 |
22 | 版本 %1$s
23 | %1$s %2$s
24 | 保留所有權利。
25 |
26 | 設定
27 |
28 | 自我檢查
29 | 確認系統是否已正確設置成microG可以使用的狀態。
30 |
31 | 允許權限
32 | 給 %1$s的權限:
33 | 按這裡給%1$s權限。不允許權限可能導致程式運作不正常。
34 |
35 | microG UI Demo
36 | 大綱
37 | 版本 v0.1.0
38 | 使用的程式庫
39 |
40 | v4 Support Library
41 | v7 appcompat Support Library
42 | v7 preference Support Library
43 | Apache License 2.0, The Android Open Source Project
44 |
45 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/app_bar.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
26 |
32 |
33 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/ToggleSwitch.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 The Android Open Source Project
3 | * Copyright (C) 2014-2017 microG Project Team
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package org.microg.tools.ui;
19 |
20 | import android.annotation.SuppressLint;
21 | import android.content.Context;
22 | import android.support.v7.widget.SwitchCompat;
23 | import android.util.AttributeSet;
24 |
25 | @SuppressLint("NewApi")
26 | public class ToggleSwitch extends SwitchCompat {
27 |
28 | private ToggleSwitch.OnBeforeCheckedChangeListener mOnBeforeListener;
29 |
30 | public interface OnBeforeCheckedChangeListener {
31 | boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked);
32 | }
33 |
34 | public ToggleSwitch(Context context) {
35 | super(context);
36 | }
37 |
38 | public ToggleSwitch(Context context, AttributeSet attrs) {
39 | super(context, attrs);
40 | }
41 |
42 | public ToggleSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
43 | super(context, attrs, defStyleAttr);
44 | }
45 |
46 | public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
47 | mOnBeforeListener = listener;
48 | }
49 |
50 | @Override
51 | public void setChecked(boolean checked) {
52 | if (mOnBeforeListener != null
53 | && mOnBeforeListener.onBeforeCheckedChanged(this, checked)) {
54 | return;
55 | }
56 | super.setChecked(checked);
57 | }
58 |
59 | public void setCheckedInternal(boolean checked) {
60 | super.setChecked(checked);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | microG UI Tools
20 | Apache License 2.0, microG Team
21 |
22 | Version %1$s
23 | %1$s %2$s
24 | Tous droits réservés.
25 |
26 | Configuration
27 |
28 | Auto-vérification.
29 | Vérifier si le système est correctement configuré pour utiliser microG.
30 |
31 | Autorisations accordées
32 | Autorisation à %1$s :
33 | Touchez ici pour accorder l’autorisation %1$s. Des applications peuvent mal se comporter si vous ne le faites pas.
34 |
35 | Version v0.1.0
36 | Librairies incluses
37 |
38 | v4 Support Library
39 | v7 appcompat Support Library
40 | v7 preference Support Library
41 | Apache License 2.0, The Android Open Source Project
42 |
43 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | microG UI Tools
20 | Apache License 2.0, microG Team
21 |
22 | Version %1$s
23 | %1$s %2$s
24 | All rights reserved.
25 |
26 | Setup
27 |
28 | Self-Check
29 | Check if the system is correctly set up to use microG.
30 |
31 | Permissions granted
32 | Permission to %1$s:
33 | Touch here to grant permission to %1$s. Not granting the permission can result in misbehaving applications.
34 |
35 | microG UI Demo
36 | Summary
37 | Version v0.1.0
38 | Included libraries
39 |
40 | v4 Support Library
41 | v7 appcompat Support Library
42 | v7 preference Support Library
43 | Apache License 2.0, The Android Open Source Project
44 |
45 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-uk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | microG UI Tools
20 | Apache License 2.0, microG Team
21 |
22 | Версія %1$s
23 | %1$s %2$s
24 | Всі права захищено.
25 |
26 | Налаштування
27 |
28 | Само-тестування
29 | Перевірка, чи належним чином система використовує microG.
30 |
31 | Доступ надано
32 | Доступ до %1$s:
33 | Торкніться, аби надати доступ до %1$s. Без доступу не гарантується робота додатку належним чином.
34 |
35 | Демонстрація microG UI
36 | Резюме
37 | Версія v0.1.0
38 | Використані бібліотеки
39 |
40 | v4 Support Library
41 | v7 appcompat Support Library
42 | v7 preference Support Library
43 | Apache License 2.0, The Android Open Source Project
44 |
45 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | microG UI Tools
20 | Apache License 2.0, microG Team
21 |
22 | Version %1$s
23 | %1$s %2$s
24 | Alle Rechte vorbehalten.
25 |
26 | Einrichtung
27 |
28 | Selbstprüfung
29 | Prüft ob das System zur Nutzung von microG konfiguriert ist.
30 |
31 | Berechtigungen erteilt
32 | %1$s:
33 | Hier drücken um die Berechtigung \"%1$s\" zu erteilen. Verweigern einer Berechtigung kann zu Fehlverhalten in anderen Anwendungen führen.
34 |
35 | microG UI Demo
36 | Zusammenfassung
37 | Version v0.1.0
38 | Genutzte Bibliotheken
39 |
40 | v4 Support Library
41 | v7 appcompat Support Library
42 | v7 preference Support Library
43 | Apache License 2.0, The Android Open Source Project
44 |
45 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | microG UI Tools
20 | Apache License 2.0, microG Team
21 |
22 | Версия %1$s
23 | %1$s %2$s
24 | Все права защищены.
25 |
26 | Установить
27 |
28 | Проверка работоспособности
29 | Проверьте, правильно ли настроена система для использования microG.
30 |
31 | Права доступа предоставлены
32 | Разрешение для %1$s:
33 | Нажмите здесь, чтобы дать разрешение на %1$s. Непредоставление разрешения может привести некорректной работе приложения.
34 |
35 | microG UI Demo
36 | Сводка
37 | Версия v0.1.0
38 | Используемые библиотеки
39 |
40 | v4 Support Library
41 | v7 appcompat Support Library
42 | v7 preference Support Library
43 | Apache License 2.0, The Android Open Source Project
44 |
45 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.os.Bundle;
20 | import android.support.v7.widget.SwitchCompat;
21 |
22 | public abstract class SwitchBarResourceSettingsFragment extends ResourceSettingsFragment implements SwitchBar.OnSwitchChangeListener {
23 | protected SwitchBar switchBar;
24 | private SwitchCompat switchCompat;
25 | private boolean listenerSetup = false;
26 |
27 | @Override
28 | public void onActivityCreated(Bundle savedInstanceState) {
29 | super.onActivityCreated(savedInstanceState);
30 |
31 | AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity();
32 |
33 | switchBar = activity.getSwitchBar();
34 | switchBar.show();
35 | switchCompat = switchBar.getSwitch();
36 | }
37 |
38 | @Override
39 | public void onDestroyView() {
40 | super.onDestroyView();
41 | switchBar.hide();
42 | }
43 |
44 | @Override
45 | public void onResume() {
46 | super.onResume();
47 | if (!listenerSetup) {
48 | switchBar.addOnSwitchChangeListener(this);
49 | listenerSetup = true;
50 | }
51 | }
52 |
53 | @Override
54 | public void onPause() {
55 | if (listenerSetup) {
56 | switchBar.removeOnSwitchChangeListener(this);
57 | listenerSetup = false;
58 | }
59 | super.onPause();
60 | }
61 |
62 | @Override
63 | public void onSwitchChanged(SwitchCompat switchView, boolean isChecked) {
64 | if (switchView == switchCompat) {
65 | onSwitchBarChanged(isChecked);
66 | }
67 | }
68 |
69 | public abstract void onSwitchBarChanged(boolean isChecked);
70 | }
71 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/self_check_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
29 |
30 |
35 |
36 |
42 |
43 |
49 |
50 |
51 |
58 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/AbstractSettingsActivity.java:
--------------------------------------------------------------------------------
1 | package org.microg.tools.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.app.FragmentTransaction;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.MenuItem;
9 | import android.view.ViewGroup;
10 |
11 | public abstract class AbstractSettingsActivity extends AppCompatActivity {
12 | protected boolean showHomeAsUp = false;
13 | protected int preferencesResource = 0;
14 | private ViewGroup customBarContainer;
15 | protected int customBarLayout = 0;
16 | protected SwitchBar switchBar;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.settings_activity);
22 |
23 | setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
24 | if (showHomeAsUp) {
25 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
26 | }
27 |
28 | switchBar = (SwitchBar) findViewById(R.id.switch_bar);
29 |
30 | customBarContainer = (ViewGroup) findViewById(R.id.custom_bar);
31 | if (customBarLayout != 0) {
32 | customBarContainer.addView(getLayoutInflater().inflate(customBarLayout, customBarContainer, false));
33 | }
34 |
35 | getSupportFragmentManager().beginTransaction()
36 | .replace(R.id.content_wrapper, getFragment())
37 | .commit();
38 | }
39 |
40 | public void setCustomBarLayout(int layout) {
41 | customBarLayout = layout;
42 | if (customBarContainer != null) {
43 | customBarContainer.removeAllViews();
44 | customBarContainer.addView(getLayoutInflater().inflate(customBarLayout, customBarContainer, false));
45 | }
46 | }
47 |
48 | public SwitchBar getSwitchBar() {
49 | return switchBar;
50 | }
51 |
52 | public void replaceFragment(Fragment fragment) {
53 | getSupportFragmentManager().beginTransaction()
54 | .addToBackStack("root")
55 | .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
56 | .replace(R.id.content_wrapper, fragment)
57 | .commit();
58 | }
59 |
60 | @Override
61 | public boolean onOptionsItemSelected(MenuItem item) {
62 | if (item.getItemId() == android.R.id.home) {
63 | finish();
64 | return true;
65 | }
66 | return super.onOptionsItemSelected(item);
67 | }
68 |
69 | protected Fragment getFragment() {
70 | if (preferencesResource == 0) {
71 | throw new IllegalStateException("Neither preferencesResource given, nor overriden getFragment()");
72 | }
73 | ResourceSettingsFragment fragment = new ResourceSettingsFragment();
74 | Bundle b = new Bundle();
75 | b.putInt(ResourceSettingsFragment.EXTRA_PREFERENCE_RESOURCE, preferencesResource);
76 | fragment.setArguments(b);
77 | return fragment;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/DimmableIconPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.content.Context;
20 | import android.graphics.drawable.Drawable;
21 | import android.support.v7.preference.Preference;
22 | import android.support.v7.preference.PreferenceViewHolder;
23 | import android.text.TextUtils;
24 | import android.util.AttributeSet;
25 | import android.view.ViewGroup;
26 | import android.widget.LinearLayout;
27 | import android.widget.TextView;
28 |
29 | /**
30 | * A preference item that can dim the icon when it's disabled, either directly or because its parent
31 | * is disabled.
32 | */
33 | public class DimmableIconPreference extends Preference {
34 | private static final int ICON_ALPHA_ENABLED = 255;
35 | private static final int ICON_ALPHA_DISABLED = 102;
36 |
37 | private final CharSequence mContentDescription;
38 |
39 | public DimmableIconPreference(Context context) {
40 | this(context, (AttributeSet) null);
41 | }
42 |
43 | public DimmableIconPreference(Context context, AttributeSet attrs) {
44 | super(context, attrs);
45 | mContentDescription = null;
46 | }
47 |
48 | public DimmableIconPreference(Context context, CharSequence contentDescription) {
49 | super(context);
50 | mContentDescription = contentDescription;
51 | }
52 |
53 | protected boolean shouldDimIcon() {
54 | return !isEnabled();
55 | }
56 |
57 | private void dimIcon(boolean dimmed) {
58 | Drawable icon = getIcon();
59 | if (icon != null) {
60 | icon.mutate().setAlpha(dimmed ? ICON_ALPHA_DISABLED : ICON_ALPHA_ENABLED);
61 | setIcon(icon);
62 | }
63 | }
64 |
65 | @Override
66 | public void onBindViewHolder(PreferenceViewHolder view) {
67 | super.onBindViewHolder(view);
68 | if (!TextUtils.isEmpty(mContentDescription)) {
69 | final TextView titleView = (TextView) view.findViewById(android.R.id.title);
70 | titleView.setContentDescription(mContentDescription);
71 | }
72 | ViewGroup.LayoutParams layoutParams = view.findViewById(R.id.icon_frame).getLayoutParams();
73 | if (layoutParams instanceof LinearLayout.LayoutParams) {
74 | if (((LinearLayout.LayoutParams) layoutParams).leftMargin < 0) {
75 | ((LinearLayout.LayoutParams) layoutParams).leftMargin = 0;
76 | }
77 | }
78 | dimIcon(shouldDimIcon());
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/selfcheck/PermissionCheckGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.selfcheck;
18 |
19 | import android.annotation.TargetApi;
20 | import android.content.Context;
21 | import android.content.pm.PackageManager;
22 | import android.content.pm.PermissionGroupInfo;
23 | import android.content.pm.PermissionInfo;
24 | import android.support.v4.app.Fragment;
25 | import android.util.Log;
26 |
27 | import org.microg.tools.ui.R;
28 |
29 | import static android.os.Build.VERSION_CODES.M;
30 | import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative;
31 | import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive;
32 |
33 | @TargetApi(M)
34 | public class PermissionCheckGroup implements SelfCheckGroup {
35 | private static final String TAG = "SelfCheckPerms";
36 |
37 | private String[] permissions;
38 |
39 | public PermissionCheckGroup(String... permissions) {
40 | this.permissions = permissions;
41 | }
42 |
43 | @Override
44 | public String getGroupName(Context context) {
45 | return context.getString(R.string.self_check_cat_permissions);
46 | }
47 |
48 | @Override
49 | public void doChecks(Context context, ResultCollector collector) {
50 | for (String permission : permissions) {
51 | doPermissionCheck(context, collector, permission);
52 | }
53 | }
54 |
55 | private void doPermissionCheck(Context context, ResultCollector collector, final String permission) {
56 | PackageManager pm = context.getPackageManager();
57 | try {
58 | PermissionInfo info = pm.getPermissionInfo(permission, 0);
59 | PermissionGroupInfo groupInfo = info.group != null ? pm.getPermissionGroupInfo(info.group, 0) : null;
60 | CharSequence permLabel = info.loadLabel(pm);
61 | CharSequence groupLabel = groupInfo != null ? groupInfo.loadLabel(pm) : permLabel;
62 | collector.addResult(context.getString(R.string.self_check_name_permission, permLabel),
63 | context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED ? Positive : Negative,
64 | context.getString(R.string.self_check_resolution_permission, groupLabel),
65 | new SelfCheckGroup.CheckResolver() {
66 |
67 | @Override
68 | public void tryResolve(Fragment fragment) {
69 | fragment.requestPermissions(new String[]{permission}, 0);
70 | }
71 | });
72 | } catch (PackageManager.NameNotFoundException e) {
73 | Log.w(TAG, e);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/about_root.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
31 |
32 |
40 |
41 |
50 |
51 |
58 |
59 |
70 |
71 |
77 |
78 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout-v21/preference_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
31 |
32 |
42 |
43 |
49 |
50 |
51 |
57 |
58 |
65 |
66 |
75 |
76 |
77 |
78 |
79 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/AbstractDashboardActivity.java:
--------------------------------------------------------------------------------
1 | package org.microg.tools.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.Toolbar;
7 | import android.view.ViewGroup;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | public abstract class AbstractDashboardActivity extends AppCompatActivity {
13 | protected int preferencesResource = 0;
14 |
15 | private final List conditions = new ArrayList();
16 | private ViewGroup conditionContainer;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.dashboard_activity);
22 | conditionContainer = (ViewGroup) findViewById(R.id.condition_container);
23 |
24 | setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
25 |
26 | getSupportFragmentManager().beginTransaction()
27 | .replace(R.id.content_wrapper, getFragment())
28 | .commit();
29 | }
30 |
31 | @Override
32 | protected void onResume() {
33 | super.onResume();
34 | forceConditionReevaluation();
35 | }
36 |
37 | private synchronized void resetConditionViews() {
38 | conditionContainer.removeAllViews();
39 | for (Condition condition : conditions) {
40 | if (condition.isEvaluated()) {
41 | if (condition.isActive(this)) {
42 | addConditionToView(condition);
43 | }
44 | } else {
45 | evaluateConditionAsync(condition);
46 | }
47 | }
48 | }
49 |
50 | private void evaluateConditionAsync(final Condition condition) {
51 | if (condition.willBeEvaluating()) {
52 | new Thread(new Runnable() {
53 | @Override
54 | public void run() {
55 | if (condition.isActive(AbstractDashboardActivity.this)) {
56 | runOnUiThread(new Runnable() {
57 | @Override
58 | public void run() {
59 | if (conditions.contains(condition) && condition.isEvaluated()) {
60 | addConditionToView(condition);
61 | }
62 | }
63 | });
64 | }
65 | }
66 | }).start();
67 | }
68 | }
69 |
70 | protected void forceConditionReevaluation() {
71 | for (Condition condition : conditions) {
72 | condition.resetEvaluated();
73 | }
74 | resetConditionViews();
75 | }
76 |
77 | protected void addAllConditions(Condition[] conditions) {
78 | for (Condition condition : conditions) {
79 | addCondition(condition);
80 | }
81 | }
82 |
83 | protected void addCondition(Condition condition) {
84 | conditions.add(condition);
85 | if (conditionContainer == null) return;
86 | if (condition.isEvaluated()) {
87 | addConditionToView(condition);
88 | } else {
89 | evaluateConditionAsync(condition);
90 | }
91 | }
92 |
93 | private synchronized void addConditionToView(Condition condition) {
94 | for (int i = 0; i < conditionContainer.getChildCount(); i++) {
95 | if (conditionContainer.getChildAt(i).getTag() == condition) return;
96 | }
97 | conditionContainer.addView(condition.createView(this, conditionContainer));
98 | }
99 |
100 | protected void clearConditions() {
101 | conditions.clear();
102 | resetConditionViews();
103 | }
104 |
105 | protected Fragment getFragment() {
106 | if (preferencesResource == 0) {
107 | throw new IllegalStateException("Neither preferencesResource given, nor overriden getFragment()");
108 | }
109 | ResourceSettingsFragment fragment = new ResourceSettingsFragment();
110 | Bundle b = new Bundle();
111 | b.putInt(ResourceSettingsFragment.EXTRA_PREFERENCE_RESOURCE, preferencesResource);
112 | fragment.setArguments(b);
113 | return fragment;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/DialogPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.content.Context;
20 | import android.content.SharedPreferences;
21 | import android.os.Bundle;
22 | import android.support.v4.app.DialogFragment;
23 | import android.support.v7.preference.Preference;
24 | import android.support.v7.preference.PreferenceDialogFragmentCompat;
25 | import android.support.v7.preference.PreferenceFragmentCompat;
26 | import android.support.v7.preference.PreferenceViewHolder;
27 | import android.util.AttributeSet;
28 | import android.view.View;
29 | import android.view.ViewGroup;
30 | import android.widget.LinearLayout;
31 |
32 | public class DialogPreference extends android.support.v7.preference.DialogPreference implements PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
33 |
34 | private static final String DIALOG_FRAGMENT_TAG =
35 | "android.support.v7.preference.PreferenceFragment.DIALOG";
36 |
37 | public DialogPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
38 | super(context, attrs, defStyleAttr, defStyleRes);
39 | }
40 |
41 | public DialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
42 | super(context, attrs, defStyleAttr);
43 | }
44 |
45 | public DialogPreference(Context context, AttributeSet attrs) {
46 | super(context, attrs);
47 | }
48 |
49 | public DialogPreference(Context context) {
50 | super(context);
51 | }
52 |
53 | protected View onCreateDialogView() {
54 | return null;
55 | }
56 |
57 | /**
58 | * Called when the dialog is dismissed and should be used to save data to
59 | * the {@link SharedPreferences}.
60 | *
61 | * @param positiveResult Whether the positive button was clicked (true), or
62 | * the negative button was clicked or the dialog was canceled (false).
63 | */
64 | protected void onDialogClosed(boolean positiveResult) {
65 | }
66 |
67 | @Override
68 | public boolean onPreferenceDisplayDialog(PreferenceFragmentCompat caller, Preference pref) {
69 | DialogPreferenceCompatDialogFragment fragment = new DialogPreferenceCompatDialogFragment();
70 | fragment.setTargetFragment(caller, 0);
71 | fragment.show(caller.getFragmentManager(), DIALOG_FRAGMENT_TAG);
72 | return true;
73 | }
74 |
75 | @Override
76 | public void onBindViewHolder(PreferenceViewHolder view) {
77 | super.onBindViewHolder(view);
78 |
79 | ViewGroup.LayoutParams layoutParams = view.findViewById(R.id.icon_frame).getLayoutParams();
80 | if (layoutParams instanceof LinearLayout.LayoutParams) {
81 | if (((LinearLayout.LayoutParams) layoutParams).leftMargin < 0) {
82 | ((LinearLayout.LayoutParams) layoutParams).leftMargin = 0;
83 | }
84 | }
85 | }
86 |
87 | public static class DialogPreferenceCompatDialogFragment extends PreferenceDialogFragmentCompat {
88 |
89 | @Override
90 | protected View onCreateDialogView(Context context) {
91 | if (getPreference() instanceof DialogPreference) {
92 | View view = ((DialogPreference) getPreference()).onCreateDialogView();
93 | if (view != null) return view;
94 | }
95 | return super.onCreateDialogView(context);
96 | }
97 |
98 | @Override
99 | public void onDialogClosed(boolean positiveResult) {
100 | if (getPreference() instanceof DialogPreference) {
101 | ((DialogPreference) getPreference()).onDialogClosed(positiveResult);
102 | }
103 | }
104 |
105 | public static DialogFragment newInstance(String key) {
106 | final DialogPreferenceCompatDialogFragment fragment = new DialogPreferenceCompatDialogFragment();
107 | final Bundle b = new Bundle(1);
108 | b.putString(ARG_KEY, key);
109 | fragment.setArguments(b);
110 | return fragment;
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/AbstractSelfCheckFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.os.Bundle;
20 | import android.support.annotation.Nullable;
21 | import android.support.v4.app.Fragment;
22 | import android.util.Log;
23 | import android.view.LayoutInflater;
24 | import android.view.MotionEvent;
25 | import android.view.View;
26 | import android.view.ViewGroup;
27 | import android.widget.CheckBox;
28 | import android.widget.TextView;
29 |
30 | import org.microg.tools.selfcheck.SelfCheckGroup;
31 |
32 | import java.util.ArrayList;
33 | import java.util.List;
34 |
35 | import static android.view.View.GONE;
36 | import static android.view.View.INVISIBLE;
37 | import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative;
38 | import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive;
39 | import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Unknown;
40 |
41 | public abstract class AbstractSelfCheckFragment extends Fragment {
42 | private static final String TAG = "SelfCheck";
43 |
44 | private ViewGroup root;
45 |
46 | @Nullable
47 | @Override
48 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
49 | View scrollRoot = inflater.inflate(R.layout.self_check, container, false);
50 | root = (ViewGroup) scrollRoot.findViewById(R.id.self_check_root);
51 | reset(inflater);
52 | return scrollRoot;
53 | }
54 |
55 | protected abstract void prepareSelfCheckList(List checks);
56 |
57 | protected void reset(LayoutInflater inflater) {
58 | List selfCheckGroupList = new ArrayList();
59 | prepareSelfCheckList(selfCheckGroupList);
60 |
61 | root.removeAllViews();
62 | for (SelfCheckGroup group : selfCheckGroupList) {
63 | View groupView = inflater.inflate(R.layout.self_check_group, root, false);
64 | ((TextView) groupView.findViewById(android.R.id.title)).setText(group.getGroupName(getContext()));
65 | final ViewGroup viewGroup = (ViewGroup) groupView.findViewById(R.id.group_content);
66 | final SelfCheckGroup.ResultCollector collector = new GroupResultCollector(viewGroup);
67 | try {
68 | group.doChecks(getContext(), collector);
69 | } catch (Exception e) {
70 | Log.w(TAG, "Failed during check " + group.getGroupName(getContext()), e);
71 | collector.addResult("Self-check failed:", Negative, "An exception occurred during self-check. Please report this issue.");
72 | }
73 | root.addView(groupView);
74 | }
75 | }
76 |
77 | private class GroupResultCollector implements SelfCheckGroup.ResultCollector {
78 | private final ViewGroup viewGroup;
79 |
80 | public GroupResultCollector(ViewGroup viewGroup) {
81 | this.viewGroup = viewGroup;
82 | }
83 |
84 | @Override
85 | public void addResult(final String name, final SelfCheckGroup.Result result, final String resolution) {
86 | addResult(name, result, resolution, null);
87 | }
88 |
89 | @Override
90 | public void addResult(final String name, final SelfCheckGroup.Result result, final String resolution,
91 | final SelfCheckGroup.CheckResolver resolver) {
92 | if (result == null || getActivity() == null) return;
93 | getActivity().runOnUiThread(new Runnable() {
94 | @Override
95 | public void run() {
96 | View resultEntry = LayoutInflater.from(getContext()).inflate(R.layout.self_check_entry, viewGroup, false);
97 | ((TextView) resultEntry.findViewById(R.id.self_check_name)).setText(name);
98 | resultEntry.findViewById(R.id.self_check_result).setOnTouchListener(new View.OnTouchListener() {
99 | @Override
100 | public boolean onTouch(View v, MotionEvent event) {
101 | return true;
102 | }
103 | });
104 | if (result == Positive) {
105 | ((CheckBox) resultEntry.findViewById(R.id.self_check_result)).setChecked(true);
106 | resultEntry.findViewById(R.id.self_check_resolution).setVisibility(GONE);
107 | } else {
108 | ((TextView) resultEntry.findViewById(R.id.self_check_resolution)).setText(resolution);
109 | if (result == Unknown) {
110 | resultEntry.findViewById(R.id.self_check_result).setVisibility(INVISIBLE);
111 | }
112 | if (resolver != null) {
113 | resultEntry.setClickable(true);
114 | resultEntry.setOnClickListener(new View.OnClickListener() {
115 | @Override
116 | public void onClick(View v) {
117 | resolver.tryResolve(AbstractSelfCheckFragment.this);
118 | }
119 | });
120 | }
121 | }
122 | viewGroup.addView(resultEntry);
123 | }
124 | });
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/res/layout/condition_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
25 |
26 |
37 |
38 |
44 |
45 |
53 |
54 |
62 |
63 |
73 |
74 |
75 |
76 |
84 |
85 |
96 |
97 |
102 |
103 |
112 |
113 |
123 |
124 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/AbstractAboutFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.content.Context;
20 | import android.content.pm.PackageManager;
21 | import android.graphics.drawable.Drawable;
22 | import android.os.Bundle;
23 | import android.support.annotation.Nullable;
24 | import android.support.v4.app.Fragment;
25 | import android.text.TextUtils;
26 | import android.view.LayoutInflater;
27 | import android.view.View;
28 | import android.view.ViewGroup;
29 | import android.widget.ArrayAdapter;
30 | import android.widget.ImageView;
31 | import android.widget.ListView;
32 | import android.widget.TextView;
33 |
34 | import java.util.ArrayList;
35 | import java.util.Collections;
36 | import java.util.List;
37 | import java.util.Locale;
38 |
39 | public abstract class AbstractAboutFragment extends Fragment {
40 |
41 | protected abstract void collectLibraries(List libraries);
42 |
43 | public static Drawable getIcon(Context context) {
44 | try {
45 | PackageManager pm = context.getPackageManager();
46 | return pm.getPackageInfo(context.getPackageName(), 0).applicationInfo.loadIcon(pm);
47 | } catch (PackageManager.NameNotFoundException e) {
48 | // Never happens, self package always exists!
49 | throw new RuntimeException(e);
50 | }
51 | }
52 |
53 | public static String getAppName(Context context) {
54 | try {
55 | PackageManager pm = context.getPackageManager();
56 | CharSequence label = pm.getPackageInfo(context.getPackageName(), 0).applicationInfo.loadLabel(pm);
57 | if (TextUtils.isEmpty(label)) return context.getPackageName();
58 | return label.toString().trim();
59 | } catch (PackageManager.NameNotFoundException e) {
60 | // Never happens, self package always exists!
61 | throw new RuntimeException(e);
62 | }
63 | }
64 |
65 | protected String getAppName() {
66 | return getAppName(getContext());
67 | }
68 |
69 | public static String getLibVersion(String packageName) {
70 | try {
71 | String versionName = (String) Class.forName(packageName + ".BuildConfig").getField("VERSION_NAME").get(null);
72 | if (TextUtils.isEmpty(versionName)) return "";
73 | return versionName.trim();
74 | } catch (Exception e) {
75 | return "";
76 | }
77 | }
78 |
79 | public static String getSelfVersion(Context context) {
80 | return getLibVersion(context.getPackageName());
81 | }
82 |
83 | protected String getSelfVersion() {
84 | return getSelfVersion(getContext());
85 | }
86 |
87 | protected String getSummary() {
88 | return null;
89 | }
90 |
91 | @Nullable
92 | @Override
93 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
94 | View aboutRoot = inflater.inflate(R.layout.about_root, container, false);
95 | ((ImageView) aboutRoot.findViewById(android.R.id.icon)).setImageDrawable(getIcon(getContext()));
96 | ((TextView) aboutRoot.findViewById(android.R.id.title)).setText(getAppName());
97 | ((TextView) aboutRoot.findViewById(R.id.about_version)).setText(getString(R.string.about_version_str, getSelfVersion()));
98 | String summary = getSummary();
99 | if (summary != null) {
100 | ((TextView) aboutRoot.findViewById(android.R.id.summary)).setText(summary);
101 | aboutRoot.findViewById(android.R.id.summary).setVisibility(View.VISIBLE);
102 | }
103 |
104 | List libraries = new ArrayList();
105 | libraries.add(new Library(BuildConfig.APPLICATION_ID, getString(R.string.lib_name), getString(R.string.lib_license)));
106 | libraries.add(new Library("android.support.v4", getString(R.string.about_android_support_v4), getString(R.string.about_android_support_license)));
107 | libraries.add(new Library("android.support.v7.appcompat", getString(R.string.about_android_support_v7_appcompat), getString(R.string.about_android_support_license)));
108 | libraries.add(new Library("android.support.v7.preference#hide_version", getString(R.string.about_android_support_v7_preference), getString(R.string.about_android_support_license)));
109 | collectLibraries(libraries);
110 | Collections.sort(libraries);
111 | ((ListView) aboutRoot.findViewById(android.R.id.list)).setAdapter(new LibraryAdapter(getContext(), libraries.toArray(new Library[libraries.size()])));
112 |
113 | return aboutRoot;
114 | }
115 |
116 | private class LibraryAdapter extends ArrayAdapter {
117 |
118 | public LibraryAdapter(Context context, Library[] libraries) {
119 | super(context, android.R.layout.simple_list_item_2, android.R.id.text1, libraries);
120 | }
121 |
122 | @Override
123 | public View getView(int position, View convertView, ViewGroup parent) {
124 | View v = super.getView(position, convertView, parent);
125 | ((TextView) v.findViewById(android.R.id.text1)).setText(getString(R.string.about_name_version_str, getItem(position).name, getLibVersion(getItem(position).packageName)));
126 | ((TextView) v.findViewById(android.R.id.text2)).setText(getItem(position).copyright != null ? getItem(position).copyright : getString(R.string.about_default_license));
127 | return v;
128 | }
129 | }
130 |
131 | protected static class Library implements Comparable {
132 | private final String packageName;
133 | private final String name;
134 | private final String copyright;
135 |
136 | public Library(String packageName, String name, String copyright) {
137 | this.packageName = packageName;
138 | this.name = name;
139 | this.copyright = copyright;
140 | }
141 |
142 | @Override
143 | public String toString() {
144 | return name + ", " + copyright;
145 | }
146 |
147 | @Override
148 | public int compareTo(Library another) {
149 | return name.toLowerCase(Locale.US).compareTo(another.name.toLowerCase(Locale.US));
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 The Android Open Source Project
3 | * Copyright (C) 2014-2017 microG Project Team
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package org.microg.tools.ui;
19 |
20 | import android.content.Context;
21 | import android.os.Build;
22 | import android.os.Parcel;
23 | import android.os.Parcelable;
24 | import android.support.v7.widget.SwitchCompat;
25 | import android.text.SpannableStringBuilder;
26 | import android.text.TextUtils;
27 | import android.text.style.TextAppearanceSpan;
28 | import android.util.AttributeSet;
29 | import android.view.LayoutInflater;
30 | import android.view.View;
31 | import android.widget.CompoundButton;
32 | import android.widget.LinearLayout;
33 | import android.widget.TextView;
34 |
35 | import java.util.ArrayList;
36 |
37 | import static android.os.Build.VERSION.SDK_INT;
38 |
39 | public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener,
40 | View.OnClickListener {
41 |
42 | public static interface OnSwitchChangeListener {
43 | /**
44 | * Called when the checked state of the Switch has changed.
45 | *
46 | * @param switchView The Switch view whose state has changed.
47 | * @param isChecked The new checked state of switchView.
48 | */
49 | void onSwitchChanged(SwitchCompat switchView, boolean isChecked);
50 | }
51 |
52 | private final TextAppearanceSpan mSummarySpan;
53 |
54 | private ToggleSwitch mSwitch;
55 | private TextView mTextView;
56 | private String mLabel;
57 | private String mSummary;
58 |
59 | private ArrayList mSwitchChangeListeners =
60 | new ArrayList();
61 |
62 | public SwitchBar(Context context) {
63 | this(context, null);
64 | }
65 |
66 | public SwitchBar(Context context, AttributeSet attrs) {
67 | super(context, attrs);
68 |
69 | LayoutInflater.from(context).inflate(R.layout.switch_bar, this);
70 |
71 | mTextView = (TextView) findViewById(R.id.switch_text);
72 | if (SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
73 | mTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
74 | }
75 | mLabel = getResources().getString(R.string.abc_capital_off);
76 | mSummarySpan = new TextAppearanceSpan(context, android.support.v7.appcompat.R.style.TextAppearance_AppCompat_Widget_Switch);
77 | updateText();
78 |
79 | mSwitch = (ToggleSwitch) findViewById(R.id.switch_widget);
80 | // Prevent onSaveInstanceState() to be called as we are managing the state of the Switch
81 | // on our own
82 | mSwitch.setSaveEnabled(false);
83 | if (SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
84 | mSwitch.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
85 | }
86 |
87 | addOnSwitchChangeListener(new OnSwitchChangeListener() {
88 | @Override
89 | public void onSwitchChanged(SwitchCompat switchView, boolean isChecked) {
90 | setTextViewLabel(isChecked);
91 | }
92 | });
93 |
94 | setOnClickListener(this);
95 |
96 | // Default is hide
97 | setVisibility(View.GONE);
98 | }
99 |
100 | public void setTextViewLabel(boolean isChecked) {
101 | mLabel = getResources()
102 | .getString(isChecked ? R.string.abc_capital_on : R.string.abc_capital_off);
103 | updateText();
104 | }
105 |
106 | public void setSummary(String summary) {
107 | mSummary = summary;
108 | updateText();
109 | }
110 |
111 | private void updateText() {
112 | if (TextUtils.isEmpty(mSummary)) {
113 | mTextView.setText(mLabel);
114 | return;
115 | }
116 | final SpannableStringBuilder ssb = new SpannableStringBuilder(mLabel).append('\n');
117 | final int start = ssb.length();
118 | ssb.append(mSummary);
119 | ssb.setSpan(mSummarySpan, start, ssb.length(), 0);
120 | mTextView.setText(ssb);
121 | }
122 |
123 | public void setChecked(boolean checked) {
124 | setTextViewLabel(checked);
125 | mSwitch.setChecked(checked);
126 | }
127 |
128 | public void setCheckedInternal(boolean checked) {
129 | setTextViewLabel(checked);
130 | mSwitch.setCheckedInternal(checked);
131 | }
132 |
133 | public boolean isChecked() {
134 | return mSwitch.isChecked();
135 | }
136 |
137 | public void setEnabled(boolean enabled) {
138 | super.setEnabled(enabled);
139 | mTextView.setEnabled(enabled);
140 | mSwitch.setEnabled(enabled);
141 | }
142 |
143 | public final ToggleSwitch getSwitch() {
144 | return mSwitch;
145 | }
146 |
147 | public void show() {
148 | if (!isShowing()) {
149 | setVisibility(View.VISIBLE);
150 | mSwitch.setOnCheckedChangeListener(this);
151 | }
152 | }
153 |
154 | public void hide() {
155 | if (isShowing()) {
156 | setVisibility(View.GONE);
157 | mSwitch.setOnCheckedChangeListener(null);
158 | }
159 | }
160 |
161 | public boolean isShowing() {
162 | return (getVisibility() == View.VISIBLE);
163 | }
164 |
165 | @Override
166 | public void onClick(View v) {
167 | final boolean isChecked = !mSwitch.isChecked();
168 | setChecked(isChecked);
169 | }
170 |
171 | public void propagateChecked(boolean isChecked) {
172 | final int count = mSwitchChangeListeners.size();
173 | for (int n = 0; n < count; n++) {
174 | mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);
175 | }
176 | }
177 |
178 | @Override
179 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
180 | propagateChecked(isChecked);
181 | }
182 |
183 | public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {
184 | if (mSwitchChangeListeners.contains(listener)) {
185 | throw new IllegalStateException("Cannot add twice the same OnSwitchChangeListener");
186 | }
187 | mSwitchChangeListeners.add(listener);
188 | }
189 |
190 | public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {
191 | if (!mSwitchChangeListeners.contains(listener)) {
192 | throw new IllegalStateException("Cannot remove OnSwitchChangeListener");
193 | }
194 | mSwitchChangeListeners.remove(listener);
195 | }
196 |
197 | static class SavedState extends BaseSavedState {
198 | boolean checked;
199 | boolean visible;
200 |
201 | SavedState(Parcelable superState) {
202 | super(superState);
203 | }
204 |
205 | /**
206 | * Constructor called from {@link #CREATOR}
207 | */
208 | private SavedState(Parcel in) {
209 | super(in);
210 | checked = (Boolean) in.readValue(Boolean.class.getClassLoader());
211 | visible = (Boolean) in.readValue(Boolean.class.getClassLoader());
212 | }
213 |
214 | @Override
215 | public void writeToParcel(Parcel out, int flags) {
216 | super.writeToParcel(out, flags);
217 | out.writeValue(checked);
218 | out.writeValue(visible);
219 | }
220 |
221 | @Override
222 | public String toString() {
223 | return "SwitchBar.SavedState{"
224 | + Integer.toHexString(System.identityHashCode(this))
225 | + " checked=" + checked
226 | + " visible=" + visible + "}";
227 | }
228 |
229 | public static final Parcelable.Creator CREATOR
230 | = new Parcelable.Creator() {
231 | public SavedState createFromParcel(Parcel in) {
232 | return new SavedState(in);
233 | }
234 |
235 | public SavedState[] newArray(int size) {
236 | return new SavedState[size];
237 | }
238 | };
239 | }
240 |
241 | @Override
242 | public Parcelable onSaveInstanceState() {
243 | Parcelable superState = super.onSaveInstanceState();
244 |
245 | SavedState ss = new SavedState(superState);
246 | ss.checked = mSwitch.isChecked();
247 | ss.visible = isShowing();
248 | return ss;
249 | }
250 |
251 | @Override
252 | public void onRestoreInstanceState(Parcelable state) {
253 | SavedState ss = (SavedState) state;
254 |
255 | super.onRestoreInstanceState(ss.getSuperState());
256 |
257 | mSwitch.setCheckedInternal(ss.checked);
258 | setTextViewLabel(ss.checked);
259 | setVisibility(ss.visible ? View.VISIBLE : View.GONE);
260 | mSwitch.setOnCheckedChangeListener(ss.visible ? this : null);
261 |
262 | requestLayout();
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
--------------------------------------------------------------------------------
/microg-ui-tools/src/main/java/org/microg/tools/ui/Condition.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2017 microG Project Team
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microg.tools.ui;
18 |
19 | import android.content.Context;
20 | import android.graphics.drawable.Drawable;
21 | import android.support.annotation.DrawableRes;
22 | import android.support.annotation.PluralsRes;
23 | import android.support.annotation.StringRes;
24 | import android.support.v4.content.res.ResourcesCompat;
25 | import android.view.LayoutInflater;
26 | import android.view.View;
27 | import android.view.ViewGroup;
28 | import android.widget.Button;
29 | import android.widget.ImageView;
30 | import android.widget.TextView;
31 |
32 | public class Condition {
33 | @DrawableRes
34 | private final int iconRes;
35 | private final Drawable icon;
36 |
37 | @StringRes
38 | private final int titleRes;
39 | @PluralsRes
40 | private final int titlePluralsRes;
41 | private final CharSequence title;
42 |
43 | @StringRes
44 | private final int summaryRes;
45 | @PluralsRes
46 | private final int summaryPluralsRes;
47 | private final CharSequence summary;
48 |
49 | @StringRes
50 | private final int firstActionTextRes;
51 | @PluralsRes
52 | private final int firstActionPluralsRes;
53 | private final CharSequence firstActionText;
54 | private final View.OnClickListener firstActionListener;
55 |
56 | @StringRes
57 | private final int secondActionTextRes;
58 | @PluralsRes
59 | private final int secondActionPluralsRes;
60 | private final CharSequence secondActionText;
61 | private final View.OnClickListener secondActionListener;
62 |
63 | private final Evaluation evaluation;
64 |
65 | private boolean evaluated = false;
66 | private boolean evaluating = false;
67 | private int evaluatedPlurals = -1;
68 | private boolean active;
69 |
70 | Condition(Builder builder) {
71 | icon = builder.icon;
72 | title = builder.title;
73 | summary = builder.summary;
74 | firstActionText = builder.firstActionText;
75 | firstActionListener = builder.firstActionListener;
76 | secondActionText = builder.secondActionText;
77 | secondActionListener = builder.secondActionListener;
78 | summaryRes = builder.summaryRes;
79 | iconRes = builder.iconRes;
80 | firstActionTextRes = builder.firstActionTextRes;
81 | secondActionTextRes = builder.secondActionTextRes;
82 | titleRes = builder.titleRes;
83 | evaluation = builder.evaluation;
84 | titlePluralsRes = builder.titlePluralsRes;
85 | summaryPluralsRes = builder.summaryPluralsRes;
86 | firstActionPluralsRes = builder.firstActionPluralsRes;
87 | secondActionPluralsRes = builder.secondActionPluralsRes;
88 | }
89 |
90 | View createView(final Context context, ViewGroup container) {
91 | LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
92 | View view = inflater.inflate(R.layout.condition_card, container, false);
93 | Drawable icon = getIcon(context);
94 | if (icon != null)
95 | ((ImageView) view.findViewById(android.R.id.icon)).setImageDrawable(icon);
96 | ((TextView) view.findViewById(android.R.id.title)).setText(getTitle(context));
97 | ((TextView) view.findViewById(android.R.id.summary)).setText(getSummary(context));
98 | Button first = (Button) view.findViewById(R.id.first_action);
99 | first.setText(getFirstActionText(context));
100 | first.setOnClickListener(getFirstActionListener());
101 | CharSequence secondActionText = getSecondActionText(context);
102 | if (secondActionText != null) {
103 | Button second = (Button) view.findViewById(R.id.second_action);
104 | second.setText(secondActionText);
105 | second.setOnClickListener(getSecondActionListener());
106 | second.setVisibility(View.VISIBLE);
107 | }
108 | final View detailGroup = view.findViewById(R.id.detail_group);
109 | final ImageView expandIndicator = (ImageView) view.findViewById(R.id.expand_indicator);
110 | View.OnClickListener expandListener = new View.OnClickListener() {
111 | @Override
112 | public void onClick(View v) {
113 | if (detailGroup.getVisibility() == View.VISIBLE) {
114 | expandIndicator.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_expand_more, context.getTheme()));
115 | detailGroup.setVisibility(View.GONE);
116 | } else {
117 | expandIndicator.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_expand_less, context.getTheme()));
118 | detailGroup.setVisibility(View.VISIBLE);
119 | }
120 | }
121 | };
122 | view.findViewById(R.id.collapsed_group).setOnClickListener(expandListener);
123 | expandIndicator.setOnClickListener(expandListener);
124 | view.setTag(this);
125 | return view;
126 | }
127 |
128 | public Drawable getIcon(Context context) {
129 | if (iconRes != 0) {
130 | return ResourcesCompat.getDrawable(context.getResources(), iconRes, context.getTheme());
131 | }
132 | return icon;
133 | }
134 |
135 | public CharSequence getTitle(Context context) {
136 | if (titleRes != 0) {
137 | return context.getString(titleRes);
138 | }
139 | if (titlePluralsRes != 0) {
140 | return context.getResources().getQuantityString(titlePluralsRes, evaluatedPlurals);
141 | }
142 | return title;
143 | }
144 |
145 | public CharSequence getSummary(Context context) {
146 | if (summaryRes != 0) {
147 | return context.getString(summaryRes);
148 | }
149 | if (summaryPluralsRes != 0) {
150 | return context.getResources().getQuantityString(summaryPluralsRes, evaluatedPlurals);
151 | }
152 | return summary;
153 | }
154 |
155 | public View.OnClickListener getFirstActionListener() {
156 | return firstActionListener;
157 | }
158 |
159 | public CharSequence getFirstActionText(Context context) {
160 | if (firstActionTextRes != 0) {
161 | return context.getString(firstActionTextRes);
162 | }
163 | if (firstActionPluralsRes != 0) {
164 | return context.getResources().getQuantityString(firstActionPluralsRes, evaluatedPlurals);
165 | }
166 | return firstActionText;
167 | }
168 |
169 | public View.OnClickListener getSecondActionListener() {
170 | return secondActionListener;
171 | }
172 |
173 | public CharSequence getSecondActionText(Context context) {
174 | if (secondActionTextRes != 0) {
175 | return context.getString(secondActionTextRes);
176 | }
177 | if (secondActionPluralsRes != 0) {
178 | return context.getResources().getQuantityString(secondActionPluralsRes, evaluatedPlurals);
179 | }
180 | return secondActionText;
181 | }
182 |
183 | public synchronized boolean willBeEvaluating() {
184 | if (!evaluating && !evaluated && evaluation != null) {
185 | return evaluating = true;
186 | } else {
187 | return false;
188 | }
189 | }
190 |
191 | public boolean isEvaluated() {
192 | return evaluated || evaluation == null;
193 | }
194 |
195 | public synchronized void evaluate(Context context) {
196 | active = evaluation == null || evaluation.isActive(context);
197 | evaluatedPlurals = evaluation.getPluralsCount();
198 | evaluated = true;
199 | evaluating = false;
200 | }
201 |
202 | public boolean isActive(Context context) {
203 | if (!evaluated && evaluation != null) evaluate(context);
204 | return active;
205 | }
206 |
207 | public void resetEvaluated() {
208 | this.evaluated = false;
209 | }
210 |
211 | public static abstract class Evaluation {
212 | public abstract boolean isActive(Context context);
213 |
214 | public int getPluralsCount() {
215 | return 1;
216 | }
217 | }
218 |
219 | public static class Builder {
220 |
221 | @DrawableRes
222 | private int iconRes;
223 | private Drawable icon;
224 | @StringRes
225 | private int titleRes;
226 | @PluralsRes
227 | private int titlePluralsRes;
228 | private CharSequence title;
229 | @StringRes
230 | private int summaryRes;
231 | @PluralsRes
232 | private int summaryPluralsRes;
233 | private CharSequence summary;
234 | @StringRes
235 | private int firstActionTextRes;
236 | @PluralsRes
237 | private int firstActionPluralsRes;
238 | private CharSequence firstActionText;
239 | private View.OnClickListener firstActionListener;
240 | @StringRes
241 | private int secondActionTextRes;
242 | @PluralsRes
243 | private int secondActionPluralsRes;
244 | private CharSequence secondActionText;
245 | private View.OnClickListener secondActionListener;
246 | private Evaluation evaluation;
247 |
248 |
249 | public Builder() {
250 | }
251 |
252 | public Builder icon(Drawable val) {
253 | icon = val;
254 | return this;
255 | }
256 |
257 | public Builder icon(@DrawableRes int val) {
258 | iconRes = val;
259 | return this;
260 | }
261 |
262 | public Builder title(CharSequence val) {
263 | title = val;
264 | return this;
265 | }
266 |
267 | public Builder title(@StringRes int val) {
268 | titleRes = val;
269 | return this;
270 | }
271 |
272 | public Builder titlePlurals(@PluralsRes int val) {
273 | titlePluralsRes = val;
274 | return this;
275 | }
276 |
277 | public Builder summary(CharSequence val) {
278 | summary = val;
279 | return this;
280 | }
281 |
282 | public Builder summary(@StringRes int val) {
283 | summaryRes = val;
284 | return this;
285 | }
286 |
287 | public Builder summaryPlurals(@PluralsRes int val) {
288 | summaryPluralsRes = val;
289 | return this;
290 | }
291 |
292 | public Builder firstAction(CharSequence text, View.OnClickListener listener) {
293 | firstActionText = text;
294 | firstActionListener = listener;
295 | return this;
296 | }
297 |
298 | public Builder firstAction(@StringRes int val, View.OnClickListener listener) {
299 | firstActionTextRes = val;
300 | firstActionListener = listener;
301 | return this;
302 | }
303 |
304 | public Builder firstActionPlurals(@PluralsRes int val, View.OnClickListener listener) {
305 | firstActionPluralsRes = val;
306 | firstActionListener = listener;
307 | return this;
308 | }
309 |
310 | public Builder secondAction(CharSequence text, View.OnClickListener listener) {
311 | secondActionText = text;
312 | secondActionListener = listener;
313 | return this;
314 | }
315 |
316 | public Builder secondAction(@StringRes int val, View.OnClickListener listener) {
317 | secondActionTextRes = val;
318 | secondActionListener = listener;
319 | return this;
320 | }
321 |
322 | public Builder secondActionPlurals(@PluralsRes int val, View.OnClickListener listener) {
323 | secondActionPluralsRes = val;
324 | secondActionListener = listener;
325 | return this;
326 | }
327 |
328 | public Builder evaluation(Evaluation evaluation) {
329 | this.evaluation = evaluation;
330 | return this;
331 | }
332 |
333 | public Condition build() {
334 | return new Condition(this);
335 | }
336 | }
337 | }
338 |
--------------------------------------------------------------------------------