mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 01:51:47 +00:00
Add a desktop-like about app page
Show version, authors and useful links
This commit is contained in:
parent
988ffe92ff
commit
049cb6d6a6
@ -365,7 +365,32 @@
|
||||
android:value="org.kde.kdeconnect.UserInterface.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.UserInterface.About.EasterEggActivity"
|
||||
android:label="@string/easter_egg"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.UserInterface.About.AboutKDEActivity"
|
||||
android:label="@string/about_kde"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.UserInterface.About.LicensesActivity"
|
||||
android:label="@string/licenses"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.MainActivity" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
10
res/drawable/ic_baseline_info_24.xml
Normal file
10
res/drawable/ic_baseline_info_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
|
||||
</vector>
|
11
res/drawable/ic_baseline_send_24.xml
Normal file
11
res/drawable/ic_baseline_send_24.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
10
res/drawable/ic_baseline_web_24.xml
Normal file
10
res/drawable/ic_baseline_web_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM15,18L4,18v-4h11v4zM15,13L4,13L4,9h11v4zM20,18h-4L16,9h4v9z"/>
|
||||
</vector>
|
4
res/drawable/ic_kde_24dp.xml
Normal file
4
res/drawable/ic_kde_24dp.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<vector android:height="24dp" android:viewportHeight="48"
|
||||
android:viewportWidth="48" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#fcfcfc" android:pathData="m26.8172,6.058 l-5.9774,0.5722v24.6133l5.9142,-0.8904v-10.494l7.9499,11.6392 6.2324,-1.972 -8.1405,-11.1935 8.2042,-10.5576 -6.3594,-1.4621 -7.8865,10.5572zM13.2678,12.0558c-0.0675,0.0071 -0.1327,0.0369 -0.1834,0.0877l-2.346,2.3456c-0.0986,0.0989 -0.1172,0.2523 -0.0445,0.3721l2.7467,4.5238c-0.4872,0.819 -0.8776,1.7021 -1.1567,2.6336l-5.0426,1.0489c-0.1403,0.0291 -0.2414,0.1534 -0.2414,0.2973v3.3173c0,0.1403 0.096,0.2618 0.2312,0.2945l4.8943,1.1963c0.261,1.0789 0.6654,2.1016 1.2,3.0416l-2.833,4.32c-0.079,0.1208 -0.0625,0.2798 0.0396,0.3815l2.3452,2.3456c0.0986,0.0984 0.2526,0.1176 0.3729,0.0454l4.4393,-2.6961c0.872,0.5032 1.8124,0.8992 2.8063,1.1677l1.0358,4.98c0.0291,0.1412 0.1539,0.2414 0.2969,0.2414h3.3177c0.1395,0 0.2612,-0.0952 0.2945,-0.232l1.22,-4.9903c1.0246,-0.2765 1.9935,-0.6886 2.8869,-1.2147l4.3747,2.8684c0.1203,0.0792 0.2794,0.0633 0.3815,-0.0387l2.346,-2.3456c0.0992,-0.0992 0.117,-0.2526 0.0441,-0.3721l-1.597,-2.632 -0.5167,0.1634c-0.0753,0.0238 -0.1575,-0.0043 -0.2018,-0.0699 0,0 -1.0186,-1.4912 -2.3342,-3.4167 -1.5727,3.0779 -4.7723,5.1864 -8.4672,5.1864 -5.2496,0 -9.5055,-4.2561 -9.5055,-9.5059 0,-3.8619 2.3035,-7.1832 5.6102,-8.6711v-2.4523c-0.6018,0.2105 -1.1836,0.4644 -1.7362,0.7654 -0.0004,-0.0004 -0.0008,-0.0014 -0.0024,-0.0028l-4.4777,-2.9368c-0.0603,-0.0394 -0.1302,-0.0551 -0.1977,-0.0482z"/>
|
||||
</vector>
|
9
res/drawable/ic_kde_48dp.xml
Normal file
9
res/drawable/ic_kde_48dp.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="m26.8172,6.058 l-5.9774,0.5722v24.6133l5.9142,-0.8904v-10.494l7.9499,11.6392 6.2324,-1.972 -8.1405,-11.1935 8.2042,-10.5576 -6.3594,-1.4621 -7.8865,10.5572zM13.2678,12.0558c-0.0675,0.0071 -0.1327,0.0369 -0.1834,0.0877l-2.346,2.3456c-0.0986,0.0989 -0.1172,0.2523 -0.0445,0.3721l2.7467,4.5238c-0.4872,0.819 -0.8776,1.7021 -1.1567,2.6336l-5.0426,1.0489c-0.1403,0.0291 -0.2414,0.1534 -0.2414,0.2973v3.3173c0,0.1403 0.096,0.2618 0.2312,0.2945l4.8943,1.1963c0.261,1.0789 0.6654,2.1016 1.2,3.0416l-2.833,4.32c-0.079,0.1208 -0.0625,0.2798 0.0396,0.3815l2.3452,2.3456c0.0986,0.0984 0.2526,0.1176 0.3729,0.0454l4.4393,-2.6961c0.872,0.5032 1.8124,0.8992 2.8063,1.1677l1.0358,4.98c0.0291,0.1412 0.1539,0.2414 0.2969,0.2414h3.3177c0.1395,0 0.2612,-0.0952 0.2945,-0.232l1.22,-4.9903c1.0246,-0.2765 1.9935,-0.6886 2.8869,-1.2147l4.3747,2.8684c0.1203,0.0792 0.2794,0.0633 0.3815,-0.0387l2.346,-2.3456c0.0992,-0.0992 0.117,-0.2526 0.0441,-0.3721l-1.597,-2.632 -0.5167,0.1634c-0.0753,0.0238 -0.1575,-0.0043 -0.2018,-0.0699 0,0 -1.0186,-1.4912 -2.3342,-3.4167 -1.5727,3.0779 -4.7723,5.1864 -8.4672,5.1864 -5.2496,0 -9.5055,-4.2561 -9.5055,-9.5059 0,-3.8619 2.3035,-7.1832 5.6102,-8.6711v-2.4523c-0.6018,0.2105 -1.1836,0.4644 -1.7362,0.7654 -0.0004,-0.0004 -0.0008,-0.0014 -0.0024,-0.0028l-4.4777,-2.9368c-0.0603,-0.0394 -0.1302,-0.0551 -0.1977,-0.0482z"
|
||||
android:fillColor="#fcfcfc"/>
|
||||
</vector>
|
BIN
res/drawable/konqi.png
Normal file
BIN
res/drawable/konqi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
71
res/layout/about_person_list_item_entry.xml
Normal file
71
res/layout/about_person_list_item_entry.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="?android:attr/scrollbarSize"
|
||||
android:paddingRight="?android:attr/scrollbarSize">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_person_list_item_entry_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="17sp"
|
||||
tools:text="Konqi Konqueror" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_person_list_item_entry_task"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:visibility="gone"
|
||||
tools:text="Developer"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/about_person_list_item_entry_visit_homepage_button"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="@dimen/default_gap"
|
||||
android:layout_marginRight="@dimen/default_gap"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/visit_contributors_homepage"
|
||||
android:src="@drawable/ic_baseline_web_24"
|
||||
android:visibility="gone"
|
||||
app:tint="@color/text_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/about_person_list_item_entry_email_button"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/email_contributor"
|
||||
android:src="@drawable/ic_baseline_send_24"
|
||||
android:visibility="gone"
|
||||
app:tint="@color/text_color"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
137
res/layout/activity_about_kde.xml
Normal file
137
res/layout/activity_about_kde.xml
Normal file
@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.About.AboutKDEActivity">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/about_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_margin="24dp"
|
||||
android:text="@string/kde_be_free"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
app:drawableLeftCompat="@drawable/ic_kde_48dp"
|
||||
app:drawableStartCompat="@drawable/ic_kde_48dp"
|
||||
app:drawableTint="@color/text_color" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:card_view="https://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
card_view:cardBackgroundColor="@color/card_stroke_color"
|
||||
card_view:cardCornerRadius="12dp"
|
||||
card_view:cardElevation="5dp"
|
||||
card_view:cardUseCompatPadding="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_text_view"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="12dp"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="@string/about_kde_about" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:card_view="https://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
card_view:cardBackgroundColor="@color/card_stroke_color"
|
||||
card_view:cardCornerRadius="12dp"
|
||||
card_view:cardElevation="5dp"
|
||||
card_view:cardUseCompatPadding="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/report_bugs_or_wishes_text_view"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="12dp"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="@string/about_kde_report_bugs_or_wishes" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:card_view="https://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
card_view:cardBackgroundColor="@color/card_stroke_color"
|
||||
card_view:cardCornerRadius="12dp"
|
||||
card_view:cardElevation="5dp"
|
||||
card_view:cardUseCompatPadding="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/join_kde_text_view"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="12dp"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="@string/about_kde_join_kde" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:card_view="https://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
card_view:cardBackgroundColor="@color/card_stroke_color"
|
||||
card_view:cardCornerRadius="12dp"
|
||||
card_view:cardElevation="5dp"
|
||||
card_view:cardUseCompatPadding="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/support_kde_text_view"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="12dp"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="@string/about_kde_support_kde" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="256dp"
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/konqi"
|
||||
android:paddingBottom="12dp"
|
||||
android:src="@drawable/konqi" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
24
res/layout/activity_easter_egg.xml
Normal file
24
res/layout/activity_easter_egg.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/easter_egg_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1d99f3"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/logo"
|
||||
android:layout_width="396dp"
|
||||
android:layout_height="396dp"
|
||||
android:src="@drawable/ic_kde_48dp"
|
||||
android:contentDescription="@string/easter_egg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/angle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@android:color/white"
|
||||
tools:text="90°"/>
|
||||
</LinearLayout>
|
16
res/layout/activity_licenses.xml
Normal file
16
res/layout/activity_licenses.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.About.LicensesActivity">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/licenses_text"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
191
res/layout/fragment_about.xml
Normal file
191
res/layout/fragment_about.xml
Normal file
@ -0,0 +1,191 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/about_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:card_view="https://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/general_info_card"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp"
|
||||
card_view:cardBackgroundColor="@color/card_stroke_color"
|
||||
card_view:cardCornerRadius="12dp"
|
||||
card_view:cardElevation="5dp"
|
||||
card_view:cardUseCompatPadding="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="top"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
android:paddingBottom="4dp"
|
||||
android:contentDescription="@string/kde_connect"
|
||||
tools:src="@drawable/icon" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Application Name"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Version 1.xy.z" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textIsSelectable="true"
|
||||
android:layout_margin="12dp"
|
||||
tools:text="Application Description" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<org.kde.kdeconnect.UserInterface.About.AutoGridLayout
|
||||
android:id="@+id/info_buttons_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:columnCount="3"
|
||||
app:columnWidth="84dp"
|
||||
app:changeColumnCountIfTheyHaveOnlyOneElement="true">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/report_bug_button"
|
||||
style="@style/AboutButton">
|
||||
|
||||
<TextView
|
||||
android:text="@string/report_bug"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_bug_report_24"
|
||||
style="@style/AboutButton.TextView" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/donate_button"
|
||||
style="@style/AboutButton">
|
||||
|
||||
<TextView
|
||||
android:text="@string/donate"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_attach_money_24"
|
||||
style="@style/AboutButton.TextView" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/source_code_button"
|
||||
style="@style/AboutButton">
|
||||
|
||||
<TextView
|
||||
android:text="@string/source_code"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_code_24"
|
||||
style="@style/AboutButton.TextView" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/licenses_button"
|
||||
style="@style/AboutButton">
|
||||
|
||||
<TextView
|
||||
android:text="@string/licenses"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_gavel_24"
|
||||
style="@style/AboutButton.TextView" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/about_kde_button"
|
||||
style="@style/AboutButton">
|
||||
|
||||
<TextView
|
||||
android:text="@string/about_kde"
|
||||
app:drawableTopCompat="@drawable/ic_kde_24dp"
|
||||
style="@style/AboutButton.TextView" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/website_button"
|
||||
style="@style/AboutButton">
|
||||
|
||||
<TextView
|
||||
android:text="@string/website"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_web_24"
|
||||
style="@style/AboutButton.TextView" />
|
||||
</FrameLayout>
|
||||
</org.kde.kdeconnect.UserInterface.About.AutoGridLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:card_view="https://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp"
|
||||
card_view:cardBackgroundColor="@color/card_stroke_color"
|
||||
card_view:cardCornerRadius="12dp"
|
||||
card_view:cardElevation="5dp"
|
||||
card_view:cardUseCompatPadding="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/authors"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6" />
|
||||
|
||||
<org.kde.kdeconnect.UserInterface.About.AdapterLinearLayout
|
||||
android:id="@+id/authors_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="0dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/authors_footer_text"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingLeft="4dp"
|
||||
tools:text="Everyone else who has contributed to KDE Connect over the years"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
18
res/menu/menu_licenses.xml
Normal file
18
res/menu/menu_licenses.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:kdeconnect="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_rise_up"
|
||||
android:icon="@drawable/ic_arrow_upward_black_24dp"
|
||||
android:title="@string/rise_up"
|
||||
android:iconTint="@color/text_color"
|
||||
kdeconnect:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_rise_down"
|
||||
android:icon="@drawable/ic_arrow_downward_black_24dp"
|
||||
android:title="@string/rise_down"
|
||||
android:iconTint="@color/text_color"
|
||||
kdeconnect:showAsAction="ifRoom" />
|
||||
</menu>
|
@ -1,4 +1,12 @@
|
||||
<resources>
|
||||
<!-- A high-contrast color for important visual elements (for less important elements, use colorControlNormal instead) -->
|
||||
<attr name="colorHighContrast" format="color" />
|
||||
|
||||
<declare-styleable name="AutoGridLayout">
|
||||
<!-- The width of one column. Used to align -->
|
||||
<attr name="columnWidth" format="dimension" />
|
||||
|
||||
<!-- I think that everything is clear from the name -->
|
||||
<attr name="changeColumnCountIfTheyHaveOnlyOneElement" format="boolean" />
|
||||
</declare-styleable>
|
||||
</resources>
|
@ -454,5 +454,68 @@
|
||||
<string name="source_code">Source Code</string>
|
||||
<string name="source_code_url" translatable="false">https://invent.kde.org/network/kdeconnect-android/</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
<string name="website">Website</string>
|
||||
<string name="website_url" translatable="false">https://kdeconnect.kde.org/</string>
|
||||
|
||||
<string name="copyright_statement" translatable="false">(С) 2013-2021 The KDE Connect Developers</string>
|
||||
|
||||
<string name="about">About</string>
|
||||
<string name="authors">Authors</string>
|
||||
<string name="thanks_to">Thanks To</string>
|
||||
<string name="easter_egg">Easter Egg</string>
|
||||
<string name="email_contributor">Email contributor\n%s</string>
|
||||
<string name="visit_contributors_homepage">Visit contributor\'s homepage\n%s</string>
|
||||
<string name="version">Version %s</string>
|
||||
<string name="about_kde">About KDE</string>
|
||||
<string name="kde_be_free">KDE - Be Free!</string>
|
||||
<string name="kde">KDE</string>
|
||||
<string name="konqi">Konqi</string>
|
||||
<string name="rise_up">Rise Up</string>
|
||||
<string name="rise_down">Rise Down</string>
|
||||
|
||||
<string name="app_description">Multi-platform app that allows your devices to communicate (e.g., your phone and your computer)</string>
|
||||
|
||||
<string name="about_kde_about"><![CDATA[
|
||||
<h1>About</h1>
|
||||
<p>KDE is a world-wide community of software engineers, artists, writers, translators and creators who are committed to <a href="https://www.gnu.org/philosophy/free-sw.html">Free Software</a> development. KDE produces the Plasma desktop environment, hundreds of applications, and the many software libraries that support them.</p>
|
||||
<p>KDE is a cooperative enterprise: no single entity controls its direction or products. Instead, we work together to achieve the common goal of building the world\'s finest Free Software. Everyone is welcome to <a href="https://community.kde.org/Get_Involved">join and contribute</a> to KDE, including you.</p>
|
||||
Visit <a href="https://www.kde.org/">https://www.kde.org/</a> for more information about the KDE community and the software we produce.
|
||||
]]></string>
|
||||
|
||||
<string name="about_kde_report_bugs_or_wishes"><![CDATA[
|
||||
<h1>Report Bugs or Wishes</h1>
|
||||
<p>Software can always be improved, and the KDE team is ready to do so. However, you - the user - must tell us when something does not work as expected or could be done better.</p>
|
||||
<p>KDE has a bug tracking system. Visit <a href="https://bugs.kde.org/">https://bugs.kde.org/</a> or use the \"Report Bug\" button from the about screen to report bugs.</p>
|
||||
If you have a suggestion for improvement then you are welcome to use the bug tracking system to register your wish. Make sure you use the severity called \"Wishlist\".
|
||||
]]></string>
|
||||
|
||||
<string name="about_kde_join_kde"><![CDATA[
|
||||
<h1>Join KDE</h1>
|
||||
<p>You do not have to be a software developer to be a member of the KDE team. You can join the national teams that translate program interfaces. You can provide graphics, themes, sounds, and improved documentation. You decide!</p>
|
||||
<p>Visit <a href="https://community.kde.org/Get_Involved">https://community.kde.org/Get_Involved</a> for information on some projects in which you can participate.</p>
|
||||
If you need more information or documentation, then a visit to <a href="https://techbase.kde.org/">https://techbase.kde.org/</a> will provide you with what you need.
|
||||
]]></string>
|
||||
|
||||
<string name="about_kde_support_kde"><![CDATA[
|
||||
<h1>Support KDE</h1>
|
||||
<p>KDE software is and will always be available free of charge, however creating it is not free.</p>
|
||||
<p>To support development the KDE community has formed the KDE e.V., a non-profit organization legally founded in Germany. KDE e.V. represents the KDE community in legal and financial matters. See <a href="https://ev.kde.org/">https://ev.kde.org/</a> for information on KDE e.V.</p>
|
||||
<p>KDE benefits from many kinds of contributions, including financial. We use the funds to reimburse members and others for expenses they incur when contributing. Further funds are used for legal support and organizing conferences and meetings.</p>
|
||||
<p>We would like to encourage you to support our efforts with a financial donation, using one of the ways described at <a href="https://www.kde.org/community/donations/">https://www.kde.org/community/donations/</a>.</p>
|
||||
Thank you very much in advance for your support.
|
||||
]]></string>
|
||||
|
||||
<!-- Authors tasks -->
|
||||
<string name="maintainer_and_developer">Maintainer and developer</string>
|
||||
<string name="developer">Developer</string>
|
||||
<string name="apple_support">macOS support. Working on iOS support</string>
|
||||
<string name="bug_fixes_and_general_improvements">Bug fixes and general improvements</string>
|
||||
<string name="samoilenko_yuri_task">SFTP implementation, bug fixes and general improvements</string>
|
||||
<string name="aniket_kumar_task">SMS plugin improvements</string>
|
||||
<string name="alex_fiestas_task">Contacts plugin improvements</string>
|
||||
<string name="maxim_leshchenko_task">UI improvements and this about page</string>
|
||||
<string name="holger_kaelberer_task">Remote keyboard plugin and bug fixes</string>
|
||||
<string name="saikrishna_arcot_task">Support for using the keyboard in the remote input plugin, bug fixes and general improvements</string>
|
||||
<string name="everyone_else">Everyone else who has contributed to KDE Connect over the years</string>
|
||||
|
||||
</resources>
|
||||
|
@ -63,4 +63,20 @@
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
<item name="android:backgroundDimEnabled">false</item>
|
||||
</style>
|
||||
|
||||
<style name="AboutButton">
|
||||
<item name="android:layout_width">84dp</item>
|
||||
<item name="android:layout_height">84dp</item>
|
||||
<item name="android:layout_margin">4dp</item>
|
||||
<item name="android:background">?attr/selectableItemBackgroundBorderless</item>
|
||||
</style>
|
||||
<style name="AboutButton.TextView">
|
||||
<item name="android:layout_width">84dp</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
<item name="android:drawablePadding">4dp</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="drawableTint">@color/text_color</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
53
src/org/kde/kdeconnect/UserInterface/About/AboutData.kt
Normal file
53
src/org/kde/kdeconnect/UserInterface/About/AboutData.kt
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class AboutData(var name: String, var description: Int, var icon: Int, var versionName: String, var copyrightStatement: String? = null,
|
||||
var bugURL: String? = null, var websiteURL: String? = null, var sourceCodeURL: String? = null, var donateURL: String? = null,
|
||||
var authorsFooterText: Int? = null) : Parcelable {
|
||||
val authors: MutableList<AboutPerson> = mutableListOf()
|
||||
|
||||
constructor(parcel: Parcel) : this(parcel.readString()!!, parcel.readInt(), parcel.readInt(), parcel.readString()!!, parcel.readString(),
|
||||
parcel.readString(), parcel.readString(), parcel.readString(), parcel.readString(),
|
||||
if (parcel.readByte() == 0x01.toByte()) parcel.readInt() else null) {
|
||||
parcel.readList(authors as List<*>, AboutPerson::class.java.classLoader)
|
||||
}
|
||||
|
||||
fun getDescriptionString(context: Context): String = context.resources.getString(description)
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<AboutData> {
|
||||
override fun createFromParcel(parcel: Parcel): AboutData = AboutData(parcel)
|
||||
override fun newArray(size: Int): Array<AboutData?> = arrayOfNulls(size)
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(name)
|
||||
parcel.writeInt(description)
|
||||
parcel.writeInt(icon)
|
||||
parcel.writeString(versionName)
|
||||
parcel.writeString(copyrightStatement)
|
||||
parcel.writeList(authors.toList())
|
||||
|
||||
parcel.writeString(bugURL)
|
||||
parcel.writeString(websiteURL)
|
||||
parcel.writeString(sourceCodeURL)
|
||||
parcel.writeString(donateURL)
|
||||
|
||||
if (authorsFooterText == null) {
|
||||
parcel.writeByte(0x00)
|
||||
} else {
|
||||
parcel.writeByte(0x01)
|
||||
parcel.writeInt(authorsFooterText!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun describeContents(): Int = 0
|
||||
}
|
119
src/org/kde/kdeconnect/UserInterface/About/AboutFragment.kt
Normal file
119
src/org/kde/kdeconnect/UserInterface/About/AboutFragment.kt
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.kde.kdeconnect.UserInterface.List.ListAdapter
|
||||
import org.kde.kdeconnect.UserInterface.MainActivity
|
||||
import org.kde.kdeconnect_tp.R
|
||||
import org.kde.kdeconnect_tp.databinding.FragmentAboutBinding
|
||||
|
||||
class AboutFragment : Fragment() {
|
||||
private var binding: FragmentAboutBinding? = null
|
||||
private lateinit var aboutData: AboutData
|
||||
private var tapCount = 0
|
||||
private var firstTapMillis: Long? = null
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(aboutData: AboutData): Fragment {
|
||||
val fragment = AboutFragment()
|
||||
|
||||
val args = Bundle(1)
|
||||
args.putParcelable("ABOUT_DATA", aboutData)
|
||||
fragment.arguments = args
|
||||
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
if (activity != null) {
|
||||
(requireActivity() as MainActivity).supportActionBar?.setTitle(R.string.about)
|
||||
}
|
||||
|
||||
aboutData = requireArguments().getParcelable("ABOUT_DATA")!!
|
||||
binding = FragmentAboutBinding.inflate(inflater, container, false)
|
||||
|
||||
updateData()
|
||||
return binding!!.root
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun updateData() {
|
||||
// Update general info
|
||||
|
||||
binding!!.appName.text = aboutData.name
|
||||
binding!!.appDescription.text = this.context?.let { aboutData.getDescriptionString(it) } + if (aboutData.copyrightStatement == null) "" else "\n\n" + aboutData.copyrightStatement
|
||||
binding!!.appIcon.setImageDrawable(this.context?.let { ContextCompat.getDrawable(it, aboutData.icon) })
|
||||
binding!!.appVersion.text = this.context?.getString(R.string.version, aboutData.versionName)
|
||||
|
||||
// Setup Easter Egg onClickListener
|
||||
|
||||
binding!!.generalInfoCard.setOnClickListener {
|
||||
if (firstTapMillis == null) {
|
||||
firstTapMillis = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
if (++tapCount == 3) {
|
||||
tapCount = 0
|
||||
|
||||
if (firstTapMillis!! >= (System.currentTimeMillis() - 500)) {
|
||||
startActivity(Intent(context, EasterEggActivity::class.java))
|
||||
}
|
||||
|
||||
firstTapMillis = null
|
||||
}
|
||||
}
|
||||
|
||||
// Update button onClickListeners
|
||||
|
||||
setupInfoButton(aboutData.bugURL, binding!!.reportBugButton)
|
||||
setupInfoButton(aboutData.donateURL, binding!!.donateButton)
|
||||
setupInfoButton(aboutData.sourceCodeURL, binding!!.sourceCodeButton)
|
||||
|
||||
binding!!.licensesButton.setOnClickListener {
|
||||
startActivity(Intent(context, LicensesActivity::class.java))
|
||||
}
|
||||
|
||||
binding!!.aboutKdeButton.setOnClickListener {
|
||||
startActivity(Intent(context, AboutKDEActivity::class.java))
|
||||
}
|
||||
|
||||
setupInfoButton(aboutData.websiteURL, binding!!.websiteButton)
|
||||
|
||||
// Update authors
|
||||
binding!!.authorsList.adapter = ListAdapter(this.context, aboutData.authors.map { AboutPersonEntryItem(it) }, false)
|
||||
if (aboutData.authorsFooterText != null) {
|
||||
binding!!.authorsFooterText.text = context?.getString(aboutData.authorsFooterText!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupInfoButton(url: String?, button: FrameLayout) {
|
||||
if (url == null) {
|
||||
button.visibility = View.GONE
|
||||
} else {
|
||||
button.setOnClickListener {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
binding = null
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
import android.text.method.LinkMovementMethod
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.kde.kdeconnect.UserInterface.ThemeUtil
|
||||
import org.kde.kdeconnect_tp.R
|
||||
import org.kde.kdeconnect_tp.databinding.ActivityAboutKdeBinding
|
||||
|
||||
class AboutKDEActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
ThemeUtil.setUserPreferredTheme(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val binding = ActivityAboutKdeBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.toolbarLayout.toolbar)
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar!!.setDisplayShowHomeEnabled(true)
|
||||
|
||||
binding.aboutTextView.text = fromHtml(resources.getString(R.string.about_kde_about))
|
||||
binding.reportBugsOrWishesTextView.text = fromHtml(resources.getString(R.string.about_kde_report_bugs_or_wishes))
|
||||
binding.joinKdeTextView.text = fromHtml(resources.getString(R.string.about_kde_join_kde))
|
||||
binding.supportKdeTextView.text = fromHtml(resources.getString(R.string.about_kde_support_kde))
|
||||
|
||||
binding.aboutTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
binding.reportBugsOrWishesTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
binding.joinKdeTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
binding.supportKdeTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
|
||||
private fun fromHtml(html: String): Spanned {
|
||||
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY)
|
||||
} else {
|
||||
@Suppress("DEPRECATION") Html.fromHtml(html)
|
||||
}
|
||||
}
|
||||
}
|
35
src/org/kde/kdeconnect/UserInterface/About/AboutPerson.kt
Normal file
35
src/org/kde/kdeconnect/UserInterface/About/AboutPerson.kt
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class AboutPerson @JvmOverloads constructor(val name: String, val task: Int? = null, val emailAddress: String? = null, val webAddress: String? = null) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(parcel.readString().toString(), if (parcel.readByte() == 0x01.toByte()) parcel.readInt() else null, parcel.readString(), parcel.readString())
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(name)
|
||||
|
||||
if (task != null) {
|
||||
parcel.writeByte(0x01)
|
||||
parcel.writeInt(task)
|
||||
} else {
|
||||
parcel.writeByte(0x00)
|
||||
}
|
||||
|
||||
parcel.writeString(emailAddress)
|
||||
parcel.writeString(webAddress)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<AboutPerson> {
|
||||
override fun createFromParcel(parcel: Parcel): AboutPerson = AboutPerson(parcel)
|
||||
override fun newArray(size: Int): Array<AboutPerson?> = arrayOfNulls(size)
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import org.kde.kdeconnect.UserInterface.List.ListAdapter
|
||||
import org.kde.kdeconnect_tp.R
|
||||
import org.kde.kdeconnect_tp.databinding.AboutPersonListItemEntryBinding
|
||||
|
||||
class AboutPersonEntryItem(val person: AboutPerson) : ListAdapter.Item {
|
||||
override fun inflateView(layoutInflater: LayoutInflater): View {
|
||||
val binding = AboutPersonListItemEntryBinding.inflate(layoutInflater)
|
||||
|
||||
binding.aboutPersonListItemEntryName.text = person.name
|
||||
|
||||
if (person.task != null) {
|
||||
binding.aboutPersonListItemEntryTask.visibility = View.VISIBLE
|
||||
binding.aboutPersonListItemEntryTask.text = layoutInflater.context.getString(person.task)
|
||||
}
|
||||
|
||||
if (person.emailAddress != null) {
|
||||
binding.aboutPersonListItemEntryEmailButton.visibility = View.VISIBLE
|
||||
TooltipCompat.setTooltipText(binding.aboutPersonListItemEntryEmailButton, layoutInflater.context.getString(R.string.email_contributor, person.emailAddress))
|
||||
binding.aboutPersonListItemEntryEmailButton.setOnClickListener {
|
||||
layoutInflater.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("mailto:" + person.emailAddress)))
|
||||
}
|
||||
}
|
||||
|
||||
if (person.webAddress != null) {
|
||||
binding.aboutPersonListItemEntryVisitHomepageButton.visibility = View.VISIBLE
|
||||
TooltipCompat.setTooltipText(binding.aboutPersonListItemEntryVisitHomepageButton, layoutInflater.context.resources.getString(R.string.visit_contributors_homepage, person.webAddress))
|
||||
binding.aboutPersonListItemEntryVisitHomepageButton.setOnClickListener {
|
||||
layoutInflater.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(person.webAddress)))
|
||||
}
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.content.Context
|
||||
import android.database.DataSetObserver
|
||||
import android.util.AttributeSet
|
||||
import android.widget.Adapter
|
||||
import android.widget.LinearLayout
|
||||
|
||||
class AdapterLinearLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : LinearLayout(context, attrs, defStyle) {
|
||||
var adapter: Adapter? = null
|
||||
set(adapter) {
|
||||
if (field !== adapter) {
|
||||
field = adapter
|
||||
field?.registerDataSetObserver(dataSetObserver)
|
||||
reloadChildViews()
|
||||
}
|
||||
}
|
||||
|
||||
private val dataSetObserver: DataSetObserver = object : DataSetObserver() {
|
||||
override fun onChanged() {
|
||||
super.onChanged()
|
||||
reloadChildViews()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
adapter?.unregisterDataSetObserver(dataSetObserver)
|
||||
}
|
||||
|
||||
private fun reloadChildViews() {
|
||||
removeAllViews()
|
||||
|
||||
if (adapter != null) {
|
||||
for (position in 0 until adapter!!.count) {
|
||||
adapter!!.getView(position, null, this)?.let { addView(it) }
|
||||
}
|
||||
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.content.Context
|
||||
import org.kde.kdeconnect_tp.BuildConfig
|
||||
import org.kde.kdeconnect_tp.R
|
||||
|
||||
/**
|
||||
* Add authors and credits here
|
||||
*/
|
||||
fun getApplicationAboutData(context: Context): AboutData {
|
||||
val aboutData = AboutData(context.getString(R.string.kde_connect), R.string.app_description, R.drawable.icon, BuildConfig.VERSION_NAME, context.getString(R.string.copyright_statement),
|
||||
context.getString(R.string.report_bug_url), context.getString(R.string.website_url), context.getString(R.string.source_code_url), context.getString(R.string.donate_url),
|
||||
R.string.everyone_else)
|
||||
|
||||
aboutData.authors += AboutPerson("Albert Vaca Cintora", R.string.maintainer_and_developer, "albertvaka+kde@gmail.com")
|
||||
aboutData.authors += AboutPerson("Aleix Pol", R.string.developer, "aleixpol@kde.org")
|
||||
aboutData.authors += AboutPerson("Inoki Shaw", R.string.apple_support, "veyx.shaw@gmail.com")
|
||||
aboutData.authors += AboutPerson("Matthijs Tijink", R.string.developer, "matthijstijink@gmail.com")
|
||||
aboutData.authors += AboutPerson("Nicolas Fella", R.string.developer, "nicolas.fella@gmx.de")
|
||||
aboutData.authors += AboutPerson("Philip Cohn-Cort", R.string.developer, "cliabhach@gmail.com")
|
||||
aboutData.authors += AboutPerson("Piyush Aggarwal", R.string.developer, "piyushaggarwal002@gmail.com")
|
||||
aboutData.authors += AboutPerson("Simon Redman", R.string.developer, "simon@ergotech.com")
|
||||
aboutData.authors += AboutPerson("Erik Duisters", R.string.developer, "e.duisters1@gmail.com")
|
||||
aboutData.authors += AboutPerson("Isira Seneviratne", R.string.developer, "isirasen96@gmail.com")
|
||||
aboutData.authors += AboutPerson("Vineet Garg", R.string.developer, "grg.vineet@gmail.com")
|
||||
aboutData.authors += AboutPerson("Anjani Kumar", R.string.bug_fixes_and_general_improvements, "anjanik012@gmail.com")
|
||||
aboutData.authors += AboutPerson("Samoilenko Yuri", R.string.samoilenko_yuri_task, "kinnalru@gmail.com")
|
||||
aboutData.authors += AboutPerson("Aniket Kumar", R.string.aniket_kumar_task, "anikketkumar786@gmail.com")
|
||||
aboutData.authors += AboutPerson("Àlex Fiestas", R.string.alex_fiestas_task, "afiestas@kde.org")
|
||||
aboutData.authors += AboutPerson("Daniel Tang", R.string.bug_fixes_and_general_improvements, "danielzgtg.opensource@gmail.com")
|
||||
aboutData.authors += AboutPerson("Maxim Leshchenko", R.string.maxim_leshchenko_task, "cnmaks90@gmail.com")
|
||||
aboutData.authors += AboutPerson("Holger Kaelberer", R.string.holger_kaelberer_task, "holger.k@elberer.de")
|
||||
aboutData.authors += AboutPerson("Saikrishna Arcot", R.string.saikrishna_arcot_task, "saiarcot895@gmail.com")
|
||||
|
||||
return aboutData
|
||||
}
|
55
src/org/kde/kdeconnect/UserInterface/About/AutoGridLayout.kt
Normal file
55
src/org/kde/kdeconnect/UserInterface/About/AutoGridLayout.kt
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.gridlayout.widget.GridLayout
|
||||
import org.kde.kdeconnect_tp.R
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* GridLayout that adjusts the number of columns and rows to fill all screen space
|
||||
*/
|
||||
class AutoGridLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : GridLayout(context, attrs, defStyleAttr) {
|
||||
private var defaultColumnCount = 0
|
||||
private var columnWidth = 0
|
||||
private var changeColumnCountIfTheyHaveOnlyOneElement = false
|
||||
|
||||
init {
|
||||
var typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoGridLayout, 0, defStyleAttr)
|
||||
|
||||
try {
|
||||
columnWidth = typedArray.getDimensionPixelSize(R.styleable.AutoGridLayout_columnWidth, 0)
|
||||
changeColumnCountIfTheyHaveOnlyOneElement = typedArray.getBoolean(R.styleable.AutoGridLayout_changeColumnCountIfTheyHaveOnlyOneElement, false)
|
||||
typedArray = context.obtainStyledAttributes(attrs, intArrayOf(android.R.attr.columnCount), 0, defStyleAttr)
|
||||
defaultColumnCount = typedArray.getInt(0, 10)
|
||||
} finally {
|
||||
typedArray.recycle()
|
||||
}
|
||||
|
||||
columnCount = 1
|
||||
}
|
||||
|
||||
override fun onMeasure(widthSpec: Int, heightSpec: Int) {
|
||||
super.onMeasure(widthSpec, heightSpec)
|
||||
val width = MeasureSpec.getSize(widthSpec)
|
||||
|
||||
if (columnWidth > 0 && width > 0) {
|
||||
val totalSpace = width - paddingRight - paddingLeft
|
||||
var calculatedColumnCount = max(1, totalSpace / columnWidth)
|
||||
|
||||
if (calculatedColumnCount < childCount && changeColumnCountIfTheyHaveOnlyOneElement) {
|
||||
calculatedColumnCount = defaultColumnCount
|
||||
}
|
||||
|
||||
columnCount = calculatedColumnCount
|
||||
} else {
|
||||
columnCount = defaultColumnCount
|
||||
}
|
||||
}
|
||||
}
|
175
src/org/kde/kdeconnect/UserInterface/About/EasterEggActivity.kt
Normal file
175
src/org/kde/kdeconnect/UserInterface/About/EasterEggActivity.kt
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.graphics.Color
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
import android.hardware.SensorManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.kde.kdeconnect_tp.R
|
||||
import org.kde.kdeconnect_tp.databinding.ActivityEasterEggBinding
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.atan2
|
||||
|
||||
private val KDE_ICON_BACKGROUND_COLOR = Color.rgb(29, 153, 243)
|
||||
private val KONQI_BACKGROUND_COLOR = Color.rgb(191, 255, 0)
|
||||
|
||||
class EasterEggActivity : AppCompatActivity(), SensorEventListener {
|
||||
private var binding: ActivityEasterEggBinding? = null
|
||||
private lateinit var sensorManager: SensorManager
|
||||
private val animator = ValueAnimator()
|
||||
private var isAlreadyLongClicked = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityEasterEggBinding.inflate(layoutInflater)
|
||||
setContentView(binding!!.root)
|
||||
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
|
||||
// Make the status bar blue to make the Easter Egg beautiful
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.statusBarColor = KDE_ICON_BACKGROUND_COLOR
|
||||
window.navigationBarColor = KDE_ICON_BACKGROUND_COLOR
|
||||
setLightSystemWindowsEnabled(false)
|
||||
}
|
||||
|
||||
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
|
||||
if (hasAccelerometer()) {
|
||||
animator.addUpdateListener {
|
||||
binding!!.logo.rotation = animator.animatedValue as Float
|
||||
}
|
||||
animator.duration = 300
|
||||
} else {
|
||||
binding!!.angle.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Make Easter Egg more fun
|
||||
binding!!.easterEggLayout.setOnLongClickListener {
|
||||
if (!isAlreadyLongClicked) {
|
||||
isAlreadyLongClicked = true
|
||||
|
||||
binding!!.easterEggLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.activity_background))
|
||||
binding!!.logo.setColorFilter(ContextCompat.getColor(this, R.color.text_color))
|
||||
binding!!.angle.setTextColor(ContextCompat.getColor(this, R.color.text_color))
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
var typedArray = this.theme.obtainStyledAttributes(intArrayOf(android.R.attr.statusBarColor))
|
||||
window.statusBarColor = typedArray.getColor(0, Color.WHITE)
|
||||
window.navigationBarColor = typedArray.getColor(0, Color.WHITE)
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
typedArray = this.theme.obtainStyledAttributes(intArrayOf(android.R.attr.windowLightStatusBar))
|
||||
setLightSystemWindowsEnabled(typedArray.getBoolean(0, true))
|
||||
}
|
||||
|
||||
typedArray.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
val icon = intArrayOf(
|
||||
R.drawable.ic_action_keyboard_24dp, R.drawable.ic_action_refresh_24dp,
|
||||
R.drawable.ic_action_image_edit_24dp, R.drawable.ic_arrow_upward_black_24dp,
|
||||
R.drawable.ic_baseline_attach_money_24, R.drawable.ic_baseline_bug_report_24,
|
||||
R.drawable.ic_baseline_code_24, R.drawable.ic_baseline_gavel_24,
|
||||
R.drawable.ic_baseline_info_24, R.drawable.ic_baseline_web_24,
|
||||
R.drawable.ic_baseline_send_24, R.drawable.ic_baseline_sms_24,
|
||||
R.drawable.ic_accept_pairing_24dp, R.drawable.ic_share_white,
|
||||
R.drawable.ic_camera, R.drawable.ic_delete,
|
||||
R.drawable.ic_device_laptop_32dp, R.drawable.ic_device_phone_32dp,
|
||||
R.drawable.ic_device_tablet_32dp, R.drawable.ic_device_tv_32dp,
|
||||
R.drawable.ic_delete, R.drawable.ic_warning,
|
||||
R.drawable.ic_volume_black, R.drawable.ic_wifi,
|
||||
R.drawable.ic_add, R.drawable.touchpad_plugin_action_24dp,
|
||||
R.drawable.konqi, R.drawable.run_command_plugin_icon_24dp,
|
||||
R.drawable.ic_phonelink_36dp, R.drawable.ic_phonelink_off_36dp,
|
||||
R.drawable.ic_error_outline_48dp, R.drawable.ic_home_black_24dp,
|
||||
R.drawable.ic_settings_white_32dp, R.drawable.ic_stop,
|
||||
R.drawable.ic_rewind_black, R.drawable.ic_play_black,
|
||||
R.drawable.ic_mic_black, R.drawable.ic_pause_black,
|
||||
R.drawable.ic_volume_mute_black, R.drawable.ic_arrow_upward_black_24dp,
|
||||
R.drawable.ic_next_black, R.drawable.ic_previous_black,
|
||||
R.drawable.ic_presenter_24dp, R.drawable.ic_key,
|
||||
R.drawable.ic_keyboard_return_black_24dp, R.drawable.ic_keyboard_hide_36dp,
|
||||
R.drawable.ic_kde_24dp, R.drawable.ic_album_art_placeholder,
|
||||
R.drawable.ic_arrow_back_black_24dp, R.drawable.share_plugin_action_24dp
|
||||
).random()
|
||||
|
||||
if (icon == R.drawable.konqi) {
|
||||
binding!!.logo.clearColorFilter()
|
||||
binding!!.easterEggLayout.setBackgroundColor(KONQI_BACKGROUND_COLOR)
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.statusBarColor = KONQI_BACKGROUND_COLOR
|
||||
window.navigationBarColor = KONQI_BACKGROUND_COLOR
|
||||
}
|
||||
|
||||
isAlreadyLongClicked = false
|
||||
}
|
||||
|
||||
binding!!.logo.setImageResource(icon)
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasAccelerometer(): Boolean = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null
|
||||
|
||||
private fun setLightSystemWindowsEnabled(enabled: Boolean) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
if (enabled) {
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
} else {
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
|
||||
}
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
if (enabled) {
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||
} else {
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (hasAccelerometer()) {
|
||||
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
if (hasAccelerometer()) {
|
||||
sensorManager.unregisterListener(this)
|
||||
}
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { }
|
||||
override fun onSensorChanged(event: SensorEvent) {
|
||||
if (binding != null) {
|
||||
val axisX = event.values[0]
|
||||
val axisY = event.values[1]
|
||||
|
||||
val angle = (atan2(axisX, axisY) / (PI / 180)).toInt()
|
||||
binding!!.angle.text = angle.toString() + "°"
|
||||
|
||||
animator.setFloatValues(binding!!.logo.rotation, angle.toFloat())
|
||||
animator.start()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.kde.kdeconnect.UserInterface.ThemeUtil
|
||||
import org.kde.kdeconnect_tp.R
|
||||
import org.kde.kdeconnect_tp.databinding.ActivityLicensesBinding
|
||||
import java.nio.charset.Charset
|
||||
|
||||
class LicensesActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityLicensesBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
ThemeUtil.setUserPreferredTheme(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityLicensesBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.toolbarLayout.toolbar)
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar!!.setDisplayShowHomeEnabled(true)
|
||||
|
||||
binding.licensesText.layoutManager = LinearLayoutManager(this)
|
||||
binding.licensesText.adapter = StringListAdapter(getLicenses().split("\n\n"))
|
||||
}
|
||||
|
||||
private fun getLicenses(): String = resources.openRawResource(R.raw.license).use { inputStream -> IOUtils.toString(inputStream, Charset.defaultCharset()) }
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_licenses, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
private fun smoothScrollToPosition(position: Int) {
|
||||
val linearSmoothScroller: LinearSmoothScroller = object : LinearSmoothScroller(this) {
|
||||
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float = 2.5F / displayMetrics.densityDpi
|
||||
}
|
||||
|
||||
linearSmoothScroller.targetPosition = position
|
||||
binding.licensesText.layoutManager?.startSmoothScroll(linearSmoothScroller)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
|
||||
R.id.menu_rise_up -> {
|
||||
smoothScrollToPosition(0)
|
||||
true
|
||||
}
|
||||
R.id.menu_rise_down -> {
|
||||
smoothScrollToPosition(binding.licensesText.adapter!!.itemCount - 1)
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Maxim Leshchenko <cnmaks90@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.About
|
||||
|
||||
import android.widget.TextView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.setPadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
class StringListAdapter(private val stringList: List<String>) : RecyclerView.Adapter<StringListAdapter.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val textView = TextView(parent.context)
|
||||
textView.setPadding(8)
|
||||
return ViewHolder(textView)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
(holder.itemView as TextView).text = stringList[position]
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = stringList.size
|
||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
|
||||
}
|
@ -23,10 +23,16 @@ public class ListAdapter extends ArrayAdapter<ListAdapter.Item> {
|
||||
}
|
||||
|
||||
private final List<? extends Item> items;
|
||||
private final boolean isEnabled;
|
||||
|
||||
public ListAdapter(Context context, List<? extends Item> items) {
|
||||
this(context, items, true);
|
||||
}
|
||||
|
||||
public ListAdapter(Context context, List<? extends Item> items, boolean isEnabled) {
|
||||
super(context, 0, (List<Item>) items);
|
||||
this.items = items;
|
||||
this.isEnabled = isEnabled;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -35,4 +41,9 @@ public class ListAdapter extends ArrayAdapter<ListAdapter.Item> {
|
||||
final Item i = items.get(position);
|
||||
return i.inflateView(LayoutInflater.from(parent.getContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return isEnabled;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
@ -35,16 +34,20 @@ import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsFragment;
|
||||
import org.kde.kdeconnect.UserInterface.About.AboutFragment;
|
||||
import org.kde.kdeconnect.UserInterface.About.ApplicationAboutDataKt;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
import org.kde.kdeconnect_tp.databinding.ActivityMainBinding;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final int MENU_ENTRY_ADD_DEVICE = 1; //0 means no-selection
|
||||
private static final int MENU_ENTRY_SETTINGS = 2;
|
||||
private static final int MENU_ENTRY_ABOUT = 3;
|
||||
private static final int MENU_ENTRY_DEVICE_FIRST_ID = 1000; //All subsequent ids are devices in the menu
|
||||
private static final int MENU_ENTRY_DEVICE_UNKNOWN = 9999; //It's still a device, but we don't know which one yet
|
||||
private static final int STORAGE_lOCATION_CONFIGURED = 2020;
|
||||
@ -129,6 +132,11 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
|
||||
preferences.edit().putString(STATE_SELECTED_DEVICE, null).apply();
|
||||
setContentFragment(new SettingsFragment());
|
||||
break;
|
||||
case MENU_ENTRY_ABOUT:
|
||||
mCurrentDevice = null;
|
||||
preferences.edit().putString(STATE_SELECTED_DEVICE, null).apply();
|
||||
setContentFragment(AboutFragment.newInstance(Objects.requireNonNull(ApplicationAboutDataKt.getApplicationAboutData(this))));
|
||||
break;
|
||||
default:
|
||||
String deviceId = mMapMenuToDeviceId.get(menuItem);
|
||||
onDeviceSelected(deviceId);
|
||||
@ -187,6 +195,8 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
|
||||
} else {
|
||||
if (mCurrentMenuEntry == MENU_ENTRY_SETTINGS) {
|
||||
setContentFragment(new SettingsFragment());
|
||||
} else if (mCurrentMenuEntry == MENU_ENTRY_ABOUT) {
|
||||
setContentFragment(AboutFragment.newInstance(Objects.requireNonNull(ApplicationAboutDataKt.getApplicationAboutData(this))));
|
||||
} else {
|
||||
setContentFragment(new PairingFragment());
|
||||
}
|
||||
@ -282,6 +292,10 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
|
||||
settingsItem.setIcon(R.drawable.ic_settings_white_32dp);
|
||||
settingsItem.setCheckable(true);
|
||||
|
||||
MenuItem aboutItem = menu.add(Menu.FIRST, MENU_ENTRY_ABOUT, 1000, R.string.about);
|
||||
aboutItem.setIcon(R.drawable.ic_baseline_info_24);
|
||||
aboutItem.setCheckable(true);
|
||||
|
||||
//Ids might have changed
|
||||
if (mCurrentMenuEntry >= MENU_ENTRY_DEVICE_FIRST_ID) {
|
||||
mCurrentMenuEntry = deviceIdToMenuEntryId(mCurrentDevice);
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.kde.kdeconnect.UserInterface;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
@ -32,33 +31,6 @@ import java.nio.charset.Charset;
|
||||
|
||||
public class SettingsFragment extends PreferenceFragmentCompat {
|
||||
|
||||
private static class LicenseTextSingleton {
|
||||
private static volatile String licenseText;
|
||||
|
||||
// Need these separate methods because Context is required to load the string
|
||||
// Mixing Context and static here is fine because the license
|
||||
// is a pure function of the project directory (i.e. doesn't depend on language, etc.)
|
||||
|
||||
static synchronized String getOrLoadLicenseText(Context context) {
|
||||
String licenseText = LicenseTextSingleton.licenseText;
|
||||
if (licenseText != null) {
|
||||
return licenseText;
|
||||
}
|
||||
try (InputStream is = context.getResources().openRawResource(R.raw.license)) {
|
||||
licenseText = IOUtils.toString(is, Charset.defaultCharset());
|
||||
} catch (IOException ie) {
|
||||
throw new RuntimeException(ie);
|
||||
}
|
||||
return LicenseTextSingleton.licenseText = licenseText;
|
||||
}
|
||||
|
||||
static synchronized void startLoadingLicenseText(Context context) {
|
||||
if (licenseText == null) {
|
||||
new Thread(() -> getOrLoadLicenseText(context)).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EditTextPreference renameDevice;
|
||||
|
||||
@Override
|
||||
@ -187,40 +159,6 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||
moreSettingsText.setSummary(R.string.settings_more_settings_text);
|
||||
screen.addPreference(moreSettingsText);
|
||||
|
||||
Preference bug = new Preference(context);
|
||||
bug.setTitle(R.string.report_bug);
|
||||
bug.setPersistent(false);
|
||||
bug.setIcon(R.drawable.ic_baseline_bug_report_24);
|
||||
bug.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.report_bug_url))));
|
||||
screen.addPreference(bug);
|
||||
|
||||
Preference donate = new Preference(context);
|
||||
donate.setTitle(R.string.donate);
|
||||
donate.setPersistent(false);
|
||||
donate.setIcon(R.drawable.ic_baseline_attach_money_24);
|
||||
donate.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.donate_url))));
|
||||
screen.addPreference(donate);
|
||||
|
||||
Preference source = new Preference(context);
|
||||
source.setTitle(R.string.source_code);
|
||||
source.setPersistent(false);
|
||||
source.setIcon(R.drawable.ic_baseline_code_24);
|
||||
source.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.source_code_url))));
|
||||
screen.addPreference(source);
|
||||
|
||||
Preference licences = new Preference(context);
|
||||
licences.setTitle(R.string.licenses);
|
||||
licences.setPersistent(false);
|
||||
licences.setIcon(R.drawable.ic_baseline_gavel_24);
|
||||
licences.setOnPreferenceClickListener(preference -> {
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(LicenseTextSingleton.getOrLoadLicenseText(context))
|
||||
.create().show();
|
||||
return true;
|
||||
});
|
||||
LicenseTextSingleton.startLoadingLicenseText(context);
|
||||
screen.addPreference(licences);
|
||||
|
||||
setPreferenceScreen(screen);
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user